blob: 6049fd731924022321f6f2ecf2f7ccf715f23366 [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>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040030#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/slab.h>
32#include <linux/interrupt.h>
33#include <linux/tty.h>
34#include <linux/tty_flip.h>
35#include <linux/serial.h>
Alexey Dobriyan8561c442009-03-31 15:19:18 -070036#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/cd1400.h>
38#include <linux/sc26198.h>
39#include <linux/comstats.h>
40#include <linux/stallion.h>
41#include <linux/ioport.h>
42#include <linux/init.h>
43#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/device.h>
45#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080046#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48#include <asm/io.h>
49#include <asm/uaccess.h>
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53/*****************************************************************************/
54
55/*
56 * Define different board types. Use the standard Stallion "assigned"
57 * board numbers. Boards supported in this driver are abbreviated as
58 * EIO = EasyIO and ECH = EasyConnection 8/32.
59 */
60#define BRD_EASYIO 20
61#define BRD_ECH 21
62#define BRD_ECHMC 22
63#define BRD_ECHPCI 26
64#define BRD_ECH64PCI 27
65#define BRD_EASYIOPCI 28
66
Jiri Slaby843b5682006-12-08 02:39:12 -080067struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080068 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 int ioaddr1;
70 int ioaddr2;
71 unsigned long memaddr;
72 int irq;
73 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
Jiri Slaby843b5682006-12-08 02:39:12 -080076static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78/*****************************************************************************/
79
80/*
81 * Define some important driver characteristics. Device major numbers
82 * allocated as per Linux Device Registry.
83 */
84#ifndef STL_SIOMEMMAJOR
85#define STL_SIOMEMMAJOR 28
86#endif
87#ifndef STL_SERIALMAJOR
88#define STL_SERIALMAJOR 24
89#endif
90#ifndef STL_CALLOUTMAJOR
91#define STL_CALLOUTMAJOR 25
92#endif
93
94/*
95 * Set the TX buffer size. Bigger is better, but we don't want
96 * to chew too much memory with buffers!
97 */
98#define STL_TXBUFLOW 512
99#define STL_TXBUFSIZE 4096
100
101/*****************************************************************************/
102
103/*
104 * Define our local driver identity first. Set up stuff to deal with
105 * all the local structures required by a serial tty driver.
106 */
107static char *stl_drvtitle = "Stallion Multiport Serial Driver";
108static char *stl_drvname = "stallion";
109static char *stl_drvversion = "5.6.0";
110
111static struct tty_driver *stl_serial;
112
113/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 * Define a local default termios struct. All ports will be created
115 * with this termios initially. Basically all it defines is a raw port
116 * at 9600, 8 data bits, 1 stop bit.
117 */
Alan Cox606d0992006-12-08 02:38:45 -0800118static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
120 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800121 .c_ispeed = 9600,
122 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123};
124
125/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 * Define global place to put buffer overflow characters.
127 */
128static char stl_unwanted[SC26198_RXFIFOSIZE];
129
130/*****************************************************************************/
131
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800132static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800133static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Alan Cox31f35932009-01-02 13:45:05 +0000135static const struct tty_port_operations stl_port_ops;
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/*
138 * Per board state flags. Used with the state field of the board struct.
139 * Not really much here!
140 */
141#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800142#define STL_PROBED 0x2
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145/*
146 * Define the port structure istate flags. These set of flags are
147 * modified at interrupt time - so setting and reseting them needs
148 * to be atomic. Use the bit clear/setting routines for this.
149 */
150#define ASYI_TXBUSY 1
151#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800152#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154/*
155 * Define an array of board names as printable strings. Handy for
156 * referencing boards when printing trace and stuff.
157 */
158static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800159 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,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 "EasyIO",
180 "EC8/32-AT",
181 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800182 NULL,
183 NULL,
184 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "EC8/32-PCI",
186 "EC8/64-PCI",
187 "EasyIO-PCI",
188};
189
190/*****************************************************************************/
191
192/*
193 * Define some string labels for arguments passed from the module
194 * load line. These allow for easy board definitions, and easy
195 * modification of the io, memory and irq resoucres.
196 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800197static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198static char *board0[4];
199static char *board1[4];
200static char *board2[4];
201static char *board3[4];
202
203static char **stl_brdsp[] = {
204 (char **) &board0,
205 (char **) &board1,
206 (char **) &board2,
207 (char **) &board3
208};
209
210/*
211 * Define a set of common board names, and types. This is used to
212 * parse any module arguments.
213 */
214
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800215static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 char *name;
217 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800218} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 { "easyio", BRD_EASYIO },
220 { "eio", BRD_EASYIO },
221 { "20", BRD_EASYIO },
222 { "ec8/32", BRD_ECH },
223 { "ec8/32-at", BRD_ECH },
224 { "ec8/32-isa", BRD_ECH },
225 { "ech", BRD_ECH },
226 { "echat", BRD_ECH },
227 { "21", BRD_ECH },
228 { "ec8/32-mc", BRD_ECHMC },
229 { "ec8/32-mca", BRD_ECHMC },
230 { "echmc", BRD_ECHMC },
231 { "echmca", BRD_ECHMC },
232 { "22", BRD_ECHMC },
233 { "ec8/32-pc", BRD_ECHPCI },
234 { "ec8/32-pci", BRD_ECHPCI },
235 { "26", BRD_ECHPCI },
236 { "ec8/64-pc", BRD_ECH64PCI },
237 { "ec8/64-pci", BRD_ECH64PCI },
238 { "ech-pci", BRD_ECH64PCI },
239 { "echpci", BRD_ECH64PCI },
240 { "echpc", BRD_ECH64PCI },
241 { "27", BRD_ECH64PCI },
242 { "easyio-pc", BRD_EASYIOPCI },
243 { "easyio-pci", BRD_EASYIOPCI },
244 { "eio-pci", BRD_EASYIOPCI },
245 { "eiopci", BRD_EASYIOPCI },
246 { "28", BRD_EASYIOPCI },
247};
248
249/*
250 * Define the module agruments.
251 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253module_param_array(board0, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board1, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
257module_param_array(board2, charp, &stl_nargs, 0);
258MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
259module_param_array(board3, charp, &stl_nargs, 0);
260MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
261
262/*****************************************************************************/
263
264/*
265 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
266 * to the directly accessible io ports of these boards (not the uarts -
267 * they are in cd1400.h and sc26198.h).
268 */
269#define EIO_8PORTRS 0x04
270#define EIO_4PORTRS 0x05
271#define EIO_8PORTDI 0x00
272#define EIO_8PORTM 0x06
273#define EIO_MK3 0x03
274#define EIO_IDBITMASK 0x07
275
276#define EIO_BRDMASK 0xf0
277#define ID_BRD4 0x10
278#define ID_BRD8 0x20
279#define ID_BRD16 0x30
280
281#define EIO_INTRPEND 0x08
282#define EIO_INTEDGE 0x00
283#define EIO_INTLEVEL 0x08
284#define EIO_0WS 0x10
285
286#define ECH_ID 0xa0
287#define ECH_IDBITMASK 0xe0
288#define ECH_BRDENABLE 0x08
289#define ECH_BRDDISABLE 0x00
290#define ECH_INTENABLE 0x01
291#define ECH_INTDISABLE 0x00
292#define ECH_INTLEVEL 0x02
293#define ECH_INTEDGE 0x00
294#define ECH_INTRPEND 0x01
295#define ECH_BRDRESET 0x01
296
297#define ECHMC_INTENABLE 0x01
298#define ECHMC_BRDRESET 0x02
299
300#define ECH_PNLSTATUS 2
301#define ECH_PNL16PORT 0x20
302#define ECH_PNLIDMASK 0x07
303#define ECH_PNLXPID 0x40
304#define ECH_PNLINTRPEND 0x80
305
306#define ECH_ADDR2MASK 0x1e0
307
308/*
309 * Define the vector mapping bits for the programmable interrupt board
310 * hardware. These bits encode the interrupt for the board to use - it
311 * is software selectable (except the EIO-8M).
312 */
313static unsigned char stl_vecmap[] = {
314 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
315 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
316};
317
318/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700319 * Lock ordering is that you may not take stallion_lock holding
320 * brd_lock.
321 */
322
323static spinlock_t brd_lock; /* Guard the board mapping */
324static spinlock_t stallion_lock; /* Guard the tty driver */
325
326/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 * Set up enable and disable macros for the ECH boards. They require
328 * the secondary io address space to be activated and deactivated.
329 * This way all ECH boards can share their secondary io region.
330 * If this is an ECH-PCI board then also need to set the page pointer
331 * to point to the correct page.
332 */
333#define BRDENABLE(brdnr,pagenr) \
334 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
335 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
336 stl_brds[(brdnr)]->ioctrl); \
337 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
338 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
339
340#define BRDDISABLE(brdnr) \
341 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
342 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
343 stl_brds[(brdnr)]->ioctrl);
344
345#define STL_CD1400MAXBAUD 230400
346#define STL_SC26198MAXBAUD 460800
347
348#define STL_BAUDBASE 115200
349#define STL_CLOSEDELAY (5 * HZ / 10)
350
351/*****************************************************************************/
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353/*
354 * Define the Stallion PCI vendor and device IDs.
355 */
356#ifndef PCI_VENDOR_ID_STALLION
357#define PCI_VENDOR_ID_STALLION 0x124d
358#endif
359#ifndef PCI_DEVICE_ID_ECHPCI832
360#define PCI_DEVICE_ID_ECHPCI832 0x0000
361#endif
362#ifndef PCI_DEVICE_ID_ECHPCI864
363#define PCI_DEVICE_ID_ECHPCI864 0x0002
364#endif
365#ifndef PCI_DEVICE_ID_EIOPCI
366#define PCI_DEVICE_ID_EIOPCI 0x0003
367#endif
368
369/*
370 * Define structure to hold all Stallion PCI boards.
371 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800373static struct pci_device_id stl_pcibrds[] = {
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
375 .driver_data = BRD_ECH64PCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
377 .driver_data = BRD_EASYIOPCI },
378 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
379 .driver_data = BRD_ECHPCI },
380 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
381 .driver_data = BRD_ECHPCI },
382 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800384MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386/*****************************************************************************/
387
388/*
389 * Define macros to extract a brd/port number from a minor number.
390 */
391#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
392#define MINOR2PORT(min) ((min) & 0x3f)
393
394/*
395 * Define a baud rate table that converts termios baud rate selector
396 * into the actual baud rate value. All baud rate calculations are
397 * based on the actual baud rate required.
398 */
399static unsigned int stl_baudrates[] = {
400 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
401 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
402};
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404/*****************************************************************************/
405
406/*
407 * Declare all those functions in this driver!
408 */
409
Alan Cox894cb912009-10-13 16:34:15 +0100410static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800411static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100412static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800413static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415/*
416 * CD1400 uart specific handling functions.
417 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800418static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
419static int stl_cd1400getreg(struct stlport *portp, int regnr);
420static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
421static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
422static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800423static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800424static int stl_cd1400getsignals(struct stlport *portp);
425static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
426static void stl_cd1400ccrwait(struct stlport *portp);
427static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
428static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
429static void stl_cd1400disableintrs(struct stlport *portp);
430static void stl_cd1400sendbreak(struct stlport *portp, int len);
431static void stl_cd1400flowctrl(struct stlport *portp, int state);
432static void stl_cd1400sendflow(struct stlport *portp, int state);
433static void stl_cd1400flush(struct stlport *portp);
434static int stl_cd1400datastate(struct stlport *portp);
435static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
436static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
437static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
438static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
439static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800441static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443/*
444 * SC26198 uart specific handling functions.
445 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800446static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
447static int stl_sc26198getreg(struct stlport *portp, int regnr);
448static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
449static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
450static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
451static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800452static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800453static int stl_sc26198getsignals(struct stlport *portp);
454static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
455static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
456static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
457static void stl_sc26198disableintrs(struct stlport *portp);
458static void stl_sc26198sendbreak(struct stlport *portp, int len);
459static void stl_sc26198flowctrl(struct stlport *portp, int state);
460static void stl_sc26198sendflow(struct stlport *portp, int state);
461static void stl_sc26198flush(struct stlport *portp);
462static int stl_sc26198datastate(struct stlport *portp);
463static void stl_sc26198wait(struct stlport *portp);
464static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
465static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
466static void stl_sc26198txisr(struct stlport *port);
467static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
468static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
469static void stl_sc26198rxbadchars(struct stlport *portp);
470static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472/*****************************************************************************/
473
474/*
475 * Generic UART support structure.
476 */
477typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800478 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
479 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800480 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800481 int (*getsignals)(struct stlport *portp);
482 void (*setsignals)(struct stlport *portp, int dtr, int rts);
483 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
484 void (*startrxtx)(struct stlport *portp, int rx, int tx);
485 void (*disableintrs)(struct stlport *portp);
486 void (*sendbreak)(struct stlport *portp, int len);
487 void (*flowctrl)(struct stlport *portp, int state);
488 void (*sendflow)(struct stlport *portp, int state);
489 void (*flush)(struct stlport *portp);
490 int (*datastate)(struct stlport *portp);
491 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492} uart_t;
493
494/*
495 * Define some macros to make calling these functions nice and clean.
496 */
497#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
498#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
499#define stl_setport (* ((uart_t *) portp->uartp)->setport)
500#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
501#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
502#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
503#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
504#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
505#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
506#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
507#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
508#define stl_flush (* ((uart_t *) portp->uartp)->flush)
509#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
510
511/*****************************************************************************/
512
513/*
514 * CD1400 UART specific data initialization.
515 */
516static uart_t stl_cd1400uart = {
517 stl_cd1400panelinit,
518 stl_cd1400portinit,
519 stl_cd1400setport,
520 stl_cd1400getsignals,
521 stl_cd1400setsignals,
522 stl_cd1400enablerxtx,
523 stl_cd1400startrxtx,
524 stl_cd1400disableintrs,
525 stl_cd1400sendbreak,
526 stl_cd1400flowctrl,
527 stl_cd1400sendflow,
528 stl_cd1400flush,
529 stl_cd1400datastate,
530 stl_cd1400eiointr
531};
532
533/*
534 * Define the offsets within the register bank of a cd1400 based panel.
535 * These io address offsets are common to the EasyIO board as well.
536 */
537#define EREG_ADDR 0
538#define EREG_DATA 4
539#define EREG_RXACK 5
540#define EREG_TXACK 6
541#define EREG_MDACK 7
542
543#define EREG_BANKSIZE 8
544
545#define CD1400_CLK 25000000
546#define CD1400_CLK8M 20000000
547
548/*
549 * Define the cd1400 baud rate clocks. These are used when calculating
550 * what clock and divisor to use for the required baud rate. Also
551 * define the maximum baud rate allowed, and the default base baud.
552 */
553static int stl_cd1400clkdivs[] = {
554 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
555};
556
557/*****************************************************************************/
558
559/*
560 * SC26198 UART specific data initization.
561 */
562static uart_t stl_sc26198uart = {
563 stl_sc26198panelinit,
564 stl_sc26198portinit,
565 stl_sc26198setport,
566 stl_sc26198getsignals,
567 stl_sc26198setsignals,
568 stl_sc26198enablerxtx,
569 stl_sc26198startrxtx,
570 stl_sc26198disableintrs,
571 stl_sc26198sendbreak,
572 stl_sc26198flowctrl,
573 stl_sc26198sendflow,
574 stl_sc26198flush,
575 stl_sc26198datastate,
576 stl_sc26198intr
577};
578
579/*
580 * Define the offsets within the register bank of a sc26198 based panel.
581 */
582#define XP_DATA 0
583#define XP_ADDR 1
584#define XP_MODID 2
585#define XP_STATUS 2
586#define XP_IACK 3
587
588#define XP_BANKSIZE 4
589
590/*
591 * Define the sc26198 baud rate table. Offsets within the table
592 * represent the actual baud rate selector of sc26198 registers.
593 */
594static unsigned int sc26198_baudtable[] = {
595 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
596 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
597 230400, 460800, 921600
598};
599
Tobias Klauserfe971072006-01-09 20:54:02 -0800600#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602/*****************************************************************************/
603
604/*
605 * Define the driver info for a user level control device. Used mainly
606 * to get at port stats - only not using the port device itself.
607 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700608static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 .owner = THIS_MODULE,
Alan Cox894cb912009-10-13 16:34:15 +0100610 .unlocked_ioctl = stl_memioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800613static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800615static void stl_cd_change(struct stlport *portp)
616{
617 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100618 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800619
Alan Coxd18a7502008-10-13 10:40:07 +0100620 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800621 return;
622
623 portp->sigs = stl_getsignals(portp);
624
625 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100626 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800627
628 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100629 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100630 tty_hangup(tty);
631 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800632}
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 * Check for any arguments passed in on the module load command line.
636 */
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638/*****************************************************************************/
639
640/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 * Parse the supplied argument string, into the board conf struct.
642 */
643
Jiri Slaby40e82652006-12-08 02:38:41 -0800644static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800647 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slabya0564e12006-12-08 02:38:37 -0800649 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Jiri Slaby615e4a72006-12-08 02:38:38 -0800651 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Jiri Slabyc62429d2006-12-08 02:39:14 -0800654 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800655 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Jiri Slabyc62429d2006-12-08 02:39:14 -0800657 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
659 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800660
Tobias Klauserfe971072006-01-09 20:54:02 -0800661 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800663 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
665
666 confp->brdtype = stl_brdstr[i].type;
667
668 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800669 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800670 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 i++;
672 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800673 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800674 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 i++;
676 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800677 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800678 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100679 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
682/*****************************************************************************/
683
684/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 * Allocate a new board structure. Fill out the basic info in it.
686 */
687
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800688static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800692 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800693 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700694 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800695 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800696 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100700 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703/*****************************************************************************/
704
Alan Cox047e9652009-11-30 13:17:03 +0000705static int stl_activate(struct tty_port *port, struct tty_struct *tty)
706{
707 struct stlport *portp = container_of(port, struct stlport, port);
708 if (!portp->tx.buf) {
709 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
710 if (!portp->tx.buf)
711 return -ENOMEM;
712 portp->tx.head = portp->tx.buf;
713 portp->tx.tail = portp->tx.buf;
714 }
715 stl_setport(portp, tty->termios);
716 portp->sigs = stl_getsignals(portp);
717 stl_setsignals(portp, 1, 1);
718 stl_enablerxtx(portp, 1, 1);
719 stl_startrxtx(portp, 1, 0);
720 return 0;
721}
722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723static int stl_open(struct tty_struct *tty, struct file *filp)
724{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800725 struct stlport *portp;
726 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800727 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000728 int portnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Jiri Slabya0564e12006-12-08 02:38:37 -0800730 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
732 minordev = tty->index;
733 brdnr = MINOR2BRD(minordev);
734 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100735 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800737 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100738 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800741 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800742 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 break;
744 if (minordev < brdp->panels[panelnr]->nrports) {
745 portnr = minordev;
746 break;
747 }
748 minordev -= brdp->panels[panelnr]->nrports;
749 }
750 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100751 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800754 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100755 return -ENODEV;
Alan Coxa2d1e352010-04-23 16:01:18 +0100756
757 tty->driver_data = portp;
Alan Cox047e9652009-11-30 13:17:03 +0000758 return tty_port_open(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760}
761
762/*****************************************************************************/
763
Alan Cox31f35932009-01-02 13:45:05 +0000764static int stl_carrier_raised(struct tty_port *port)
765{
766 struct stlport *portp = container_of(port, struct stlport, port);
767 return (portp->sigs & TIOCM_CD) ? 1 : 0;
768}
769
Alan Coxfcc8ac12009-06-11 12:24:17 +0100770static void stl_dtr_rts(struct tty_port *port, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771{
Alan Cox4350f3f2009-01-02 13:46:24 +0000772 struct stlport *portp = container_of(port, struct stlport, port);
773 /* Takes brd_lock internally */
Alan Coxfcc8ac12009-06-11 12:24:17 +0100774 stl_setsignals(portp, on, on);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775}
776
777/*****************************************************************************/
778
Jiri Slaby96b066b2006-12-08 02:38:42 -0800779static void stl_flushbuffer(struct tty_struct *tty)
780{
781 struct stlport *portp;
782
783 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
784
Jiri Slaby96b066b2006-12-08 02:38:42 -0800785 portp = tty->driver_data;
786 if (portp == NULL)
787 return;
788
789 stl_flush(portp);
790 tty_wakeup(tty);
791}
792
793/*****************************************************************************/
794
795static void stl_waituntilsent(struct tty_struct *tty, int timeout)
796{
797 struct stlport *portp;
798 unsigned long tend;
799
800 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
801
Jiri Slaby96b066b2006-12-08 02:38:42 -0800802 portp = tty->driver_data;
803 if (portp == NULL)
804 return;
805
806 if (timeout == 0)
807 timeout = HZ;
808 tend = jiffies + timeout;
809
Alan Cox978e5952008-04-30 00:53:59 -0700810 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800811 while (stl_datastate(portp)) {
812 if (signal_pending(current))
813 break;
814 msleep_interruptible(20);
815 if (time_after_eq(jiffies, tend))
816 break;
817 }
Alan Cox978e5952008-04-30 00:53:59 -0700818 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800819}
820
821/*****************************************************************************/
822
Alan Cox047e9652009-11-30 13:17:03 +0000823static void stl_shutdown(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824{
Alan Cox047e9652009-11-30 13:17:03 +0000825 struct stlport *portp = container_of(port, struct stlport, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 stl_disableintrs(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 stl_enablerxtx(portp, 0, 0);
Alan Cox047e9652009-11-30 13:17:03 +0000828 stl_flush(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800830 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800832 portp->tx.buf = NULL;
833 portp->tx.head = NULL;
834 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 }
Alan Cox047e9652009-11-30 13:17:03 +0000836}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Alan Cox047e9652009-11-30 13:17:03 +0000838static void stl_close(struct tty_struct *tty, struct file *filp)
839{
840 struct stlport*portp;
841 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
842
843 portp = tty->driver_data;
Alan Coxa2d1e352010-04-23 16:01:18 +0100844 if(portp == NULL)
845 return;
Alan Cox047e9652009-11-30 13:17:03 +0000846 tty_port_close(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847}
848
849/*****************************************************************************/
850
851/*
852 * Write routine. Take data and stuff it in to the TX ring queue.
853 * If transmit interrupts are not running then start them.
854 */
855
856static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
857{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800858 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 unsigned int len, stlen;
860 unsigned char *chbuf;
861 char *head, *tail;
862
Jiri Slabya0564e12006-12-08 02:38:37 -0800863 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800866 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100867 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800868 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100869 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
871/*
872 * If copying direct from user space we must cater for page faults,
873 * causing us to "sleep" here for a while. To handle this copy in all
874 * the data we need now, into a local buffer. Then when we got it all
875 * copy it into the TX buffer.
876 */
877 chbuf = (unsigned char *) buf;
878
879 head = portp->tx.head;
880 tail = portp->tx.tail;
881 if (head >= tail) {
882 len = STL_TXBUFSIZE - (head - tail) - 1;
883 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
884 } else {
885 len = tail - head - 1;
886 stlen = len;
887 }
888
Jiri Slaby843b5682006-12-08 02:39:12 -0800889 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 count = 0;
891 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800892 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 memcpy(head, chbuf, stlen);
894 len -= stlen;
895 chbuf += stlen;
896 count += stlen;
897 head += stlen;
898 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
899 head = portp->tx.buf;
900 stlen = tail - head;
901 }
902 }
903 portp->tx.head = head;
904
905 clear_bit(ASYI_TXLOW, &portp->istate);
906 stl_startrxtx(portp, -1, 1);
907
Jesper Juhl014c2542006-01-15 02:37:08 +0100908 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909}
910
911/*****************************************************************************/
912
David Howells4a561222008-07-22 11:18:43 +0100913static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800915 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 unsigned int len;
917 char *head, *tail;
918
Jiri Slabya0564e12006-12-08 02:38:37 -0800919 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800922 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100923 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800924 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100925 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
927 head = portp->tx.head;
928 tail = portp->tx.tail;
929
930 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
931 len--;
932
933 if (len > 0) {
934 *head++ = ch;
935 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
936 head = portp->tx.buf;
937 }
938 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100939 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940}
941
942/*****************************************************************************/
943
944/*
945 * If there are any characters in the buffer then make sure that TX
946 * interrupts are on and get'em out. Normally used after the putchar
947 * routine has been called.
948 */
949
950static void stl_flushchars(struct tty_struct *tty)
951{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800952 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Jiri Slabya0564e12006-12-08 02:38:37 -0800954 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800957 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800959 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 return;
961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 stl_startrxtx(portp, -1, 1);
963}
964
965/*****************************************************************************/
966
967static int stl_writeroom(struct tty_struct *tty)
968{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800969 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 char *head, *tail;
971
Jiri Slabya0564e12006-12-08 02:38:37 -0800972 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800975 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100976 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800977 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100978 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 head = portp->tx.head;
981 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800982 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983}
984
985/*****************************************************************************/
986
987/*
988 * Return number of chars in the TX buffer. Normally we would just
989 * calculate the number of chars in the buffer and return that, but if
990 * the buffer is empty and TX interrupts are still on then we return
991 * that the buffer still has 1 char in it. This way whoever called us
992 * will not think that ALL chars have drained - since the UART still
993 * must have some chars in it (we are busy after all).
994 */
995
996static int stl_charsinbuffer(struct tty_struct *tty)
997{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800998 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 unsigned int size;
1000 char *head, *tail;
1001
Jiri Slabya0564e12006-12-08 02:38:37 -08001002 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001005 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001006 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001007 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001008 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
1010 head = portp->tx.head;
1011 tail = portp->tx.tail;
1012 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1013 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1014 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001015 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016}
1017
1018/*****************************************************************************/
1019
1020/*
1021 * Generate the serial struct info.
1022 */
1023
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001024static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025{
1026 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001027 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Jiri Slabya0564e12006-12-08 02:38:37 -08001029 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
1031 memset(&sio, 0, sizeof(struct serial_struct));
1032 sio.line = portp->portnr;
1033 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001034 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 sio.baud_base = portp->baud_base;
1036 sio.close_delay = portp->close_delay;
1037 sio.closing_wait = portp->closing_wait;
1038 sio.custom_divisor = portp->custom_divisor;
1039 sio.hub6 = 0;
1040 if (portp->uartp == &stl_cd1400uart) {
1041 sio.type = PORT_CIRRUS;
1042 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1043 } else {
1044 sio.type = PORT_UNKNOWN;
1045 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1046 }
1047
1048 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001049 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 sio.irq = brdp->irq;
1051
1052 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1053}
1054
1055/*****************************************************************************/
1056
1057/*
1058 * Set port according to the serial struct info.
1059 * At this point we do not do any auto-configure stuff, so we will
1060 * just quietly ignore any requests to change irq, etc.
1061 */
1062
Alan Coxd18a7502008-10-13 10:40:07 +01001063static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Alan Coxd18a7502008-10-13 10:40:07 +01001065 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 struct serial_struct sio;
1067
Jiri Slabya0564e12006-12-08 02:38:37 -08001068 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1071 return -EFAULT;
1072 if (!capable(CAP_SYS_ADMIN)) {
1073 if ((sio.baud_base != portp->baud_base) ||
1074 (sio.close_delay != portp->close_delay) ||
1075 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001076 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001077 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 }
1079
Alan Coxf8ae4762008-07-16 21:56:37 +01001080 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 (sio.flags & ASYNC_USR_MASK);
1082 portp->baud_base = sio.baud_base;
1083 portp->close_delay = sio.close_delay;
1084 portp->closing_wait = sio.closing_wait;
1085 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001086 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001087 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088}
1089
1090/*****************************************************************************/
1091
1092static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1093{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001094 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001097 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001098 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001100 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 return stl_getsignals(portp);
1103}
1104
1105static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1106 unsigned int set, unsigned int clear)
1107{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001108 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 int rts = -1, dtr = -1;
1110
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001112 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001113 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001115 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
1117 if (set & TIOCM_RTS)
1118 rts = 1;
1119 if (set & TIOCM_DTR)
1120 dtr = 1;
1121 if (clear & TIOCM_RTS)
1122 rts = 0;
1123 if (clear & TIOCM_DTR)
1124 dtr = 0;
1125
1126 stl_setsignals(portp, dtr, rts);
1127 return 0;
1128}
1129
1130static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1131{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001132 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 int rc;
1134 void __user *argp = (void __user *)arg;
1135
Jiri Slabya0564e12006-12-08 02:38:37 -08001136 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1137 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001140 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001141 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001144 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001146 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
1148 rc = 0;
1149
Alan Coxf433c652008-04-30 00:53:23 -07001150 lock_kernel();
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 case TIOCGSERIAL:
1154 rc = stl_getserial(portp, argp);
1155 break;
1156 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001157 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 break;
1159 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001160 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 break;
1162 case COM_CLRPORTSTATS:
1163 rc = stl_clrportstats(portp, argp);
1164 break;
1165 case TIOCSERCONFIG:
1166 case TIOCSERGWILD:
1167 case TIOCSERSWILD:
1168 case TIOCSERGETLSR:
1169 case TIOCSERGSTRUCT:
1170 case TIOCSERGETMULTI:
1171 case TIOCSERSETMULTI:
1172 default:
1173 rc = -ENOIOCTLCMD;
1174 break;
1175 }
Alan Coxf433c652008-04-30 00:53:23 -07001176 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001177 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178}
1179
1180/*****************************************************************************/
1181
Jiri Slaby96b066b2006-12-08 02:38:42 -08001182/*
1183 * Start the transmitter again. Just turn TX interrupts back on.
1184 */
1185
1186static void stl_start(struct tty_struct *tty)
1187{
1188 struct stlport *portp;
1189
1190 pr_debug("stl_start(tty=%p)\n", tty);
1191
Jiri Slaby96b066b2006-12-08 02:38:42 -08001192 portp = tty->driver_data;
1193 if (portp == NULL)
1194 return;
1195 stl_startrxtx(portp, -1, 1);
1196}
1197
1198/*****************************************************************************/
1199
Alan Cox606d0992006-12-08 02:38:45 -08001200static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001202 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001203 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204
Jiri Slabya0564e12006-12-08 02:38:37 -08001205 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001208 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 return;
1210
1211 tiosp = tty->termios;
1212 if ((tiosp->c_cflag == old->c_cflag) &&
1213 (tiosp->c_iflag == old->c_iflag))
1214 return;
1215
1216 stl_setport(portp, tiosp);
1217 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1218 -1);
1219 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1220 tty->hw_stopped = 0;
1221 stl_start(tty);
1222 }
1223 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001224 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225}
1226
1227/*****************************************************************************/
1228
1229/*
1230 * Attempt to flow control who ever is sending us data. Based on termios
1231 * settings use software or/and hardware flow control.
1232 */
1233
1234static void stl_throttle(struct tty_struct *tty)
1235{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001236 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Jiri Slabya0564e12006-12-08 02:38:37 -08001238 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001241 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 return;
1243 stl_flowctrl(portp, 0);
1244}
1245
1246/*****************************************************************************/
1247
1248/*
1249 * Unflow control the device sending us data...
1250 */
1251
1252static void stl_unthrottle(struct tty_struct *tty)
1253{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001254 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
Jiri Slabya0564e12006-12-08 02:38:37 -08001256 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001259 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 return;
1261 stl_flowctrl(portp, 1);
1262}
1263
1264/*****************************************************************************/
1265
1266/*
1267 * Stop the transmitter. Basically to do this we will just turn TX
1268 * interrupts off.
1269 */
1270
1271static void stl_stop(struct tty_struct *tty)
1272{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001273 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Jiri Slabya0564e12006-12-08 02:38:37 -08001275 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001278 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 return;
1280 stl_startrxtx(portp, -1, 0);
1281}
1282
1283/*****************************************************************************/
1284
1285/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 * Hangup this port. This is pretty much like closing the port, only
1287 * a little more brutal. No waiting for data to drain. Shutdown the
1288 * port and maybe drop signals.
1289 */
1290
1291static void stl_hangup(struct tty_struct *tty)
1292{
Alan Cox047e9652009-11-30 13:17:03 +00001293 struct stlport *portp = tty->driver_data;
Jiri Slabya0564e12006-12-08 02:38:37 -08001294 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Jiri Slaby615e4a72006-12-08 02:38:38 -08001296 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 return;
Alan Cox047e9652009-11-30 13:17:03 +00001298 tty_port_hangup(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299}
1300
1301/*****************************************************************************/
1302
David Howells4a561222008-07-22 11:18:43 +01001303static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001305 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Jiri Slabya0564e12006-12-08 02:38:37 -08001307 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001310 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001311 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
1313 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001314 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315}
1316
1317/*****************************************************************************/
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319static void stl_sendxchar(struct tty_struct *tty, char ch)
1320{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001321 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Jiri Slabya0564e12006-12-08 02:38:37 -08001323 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001326 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 return;
1328
1329 if (ch == STOP_CHAR(tty))
1330 stl_sendflow(portp, 0);
1331 else if (ch == START_CHAR(tty))
1332 stl_sendflow(portp, 1);
1333 else
1334 stl_putchar(tty, ch);
1335}
1336
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001337static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001339 int sigs;
1340 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001342 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1344 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1345
1346 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001347 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001349 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001351 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001353 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
1355 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001356 sep = ' ';
1357 if (sigs & TIOCM_RTS) {
1358 seq_printf(m, "%c%s", sep, "RTS");
1359 sep = '|';
1360 }
1361 if (sigs & TIOCM_CTS) {
1362 seq_printf(m, "%c%s", sep, "CTS");
1363 sep = '|';
1364 }
1365 if (sigs & TIOCM_DTR) {
1366 seq_printf(m, "%c%s", sep, "DTR");
1367 sep = '|';
1368 }
1369 if (sigs & TIOCM_CD) {
1370 seq_printf(m, "%c%s", sep, "DCD");
1371 sep = '|';
1372 }
1373 if (sigs & TIOCM_DSR) {
1374 seq_printf(m, "%c%s", sep, "DSR");
1375 sep = '|';
1376 }
1377 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378}
1379
1380/*****************************************************************************/
1381
1382/*
1383 * Port info, read from the /proc file system.
1384 */
1385
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001386static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001388 struct stlbrd *brdp;
1389 struct stlpanel *panelp;
1390 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001391 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001392 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001396 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
1398/*
1399 * We scan through for each board, panel and port. The offset is
1400 * calculated on the fly, and irrelevant ports are skipped.
1401 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001402 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001404 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 continue;
1406 if (brdp->state == 0)
1407 continue;
1408
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001410 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001412 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 continue;
1414
Jiri Slabyc62429d2006-12-08 02:39:14 -08001415 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 totalport++) {
1417 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001418 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001420 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 }
1422 }
1423 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001424 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425}
1426
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001427static int stl_proc_open(struct inode *inode, struct file *file)
1428{
1429 return single_open(file, stl_proc_show, NULL);
1430}
1431
1432static const struct file_operations stl_proc_fops = {
1433 .owner = THIS_MODULE,
1434 .open = stl_proc_open,
1435 .read = seq_read,
1436 .llseek = seq_lseek,
1437 .release = single_release,
1438};
1439
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440/*****************************************************************************/
1441
1442/*
1443 * All board interrupts are vectored through here first. This code then
1444 * calls off to the approrpriate board interrupt handlers.
1445 */
1446
David Howells7d12e782006-10-05 14:55:46 +01001447static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001449 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
Jeff Garzika6f97b22007-10-31 05:20:49 -04001451 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
1453 return IRQ_RETVAL((* brdp->isr)(brdp));
1454}
1455
1456/*****************************************************************************/
1457
1458/*
1459 * Interrupt service routine for EasyIO board types.
1460 */
1461
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001462static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001464 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 unsigned int iobase;
1466 int handled = 0;
1467
Alan Coxb65b5b52006-06-27 02:54:05 -07001468 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 panelp = brdp->panels[0];
1470 iobase = panelp->iobase;
1471 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1472 handled = 1;
1473 (* panelp->isr)(panelp, iobase);
1474 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001475 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 return handled;
1477}
1478
1479/*****************************************************************************/
1480
1481/*
1482 * Interrupt service routine for ECH-AT board types.
1483 */
1484
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001485static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001487 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001488 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 int handled = 0;
1490
1491 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1492
1493 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1494 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001495 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 ioaddr = brdp->bnkstataddr[bnknr];
1497 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1498 panelp = brdp->bnk2panel[bnknr];
1499 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1500 }
1501 }
1502 }
1503
1504 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1505
1506 return handled;
1507}
1508
1509/*****************************************************************************/
1510
1511/*
1512 * Interrupt service routine for ECH-MCA board types.
1513 */
1514
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001515static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001517 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001518 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 int handled = 0;
1520
1521 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1522 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001523 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 ioaddr = brdp->bnkstataddr[bnknr];
1525 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1526 panelp = brdp->bnk2panel[bnknr];
1527 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1528 }
1529 }
1530 }
1531 return handled;
1532}
1533
1534/*****************************************************************************/
1535
1536/*
1537 * Interrupt service routine for ECH-PCI board types.
1538 */
1539
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001540static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001542 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001543 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 int handled = 0;
1545
1546 while (1) {
1547 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001548 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1550 ioaddr = brdp->bnkstataddr[bnknr];
1551 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1552 panelp = brdp->bnk2panel[bnknr];
1553 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1554 recheck++;
1555 handled = 1;
1556 }
1557 }
1558 if (! recheck)
1559 break;
1560 }
1561 return handled;
1562}
1563
1564/*****************************************************************************/
1565
1566/*
1567 * Interrupt service routine for ECH-8/64-PCI board types.
1568 */
1569
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001570static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001572 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001573 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 int handled = 0;
1575
1576 while (inb(brdp->ioctrl) & 0x1) {
1577 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001578 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 ioaddr = brdp->bnkstataddr[bnknr];
1580 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1581 panelp = brdp->bnk2panel[bnknr];
1582 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1583 }
1584 }
1585 }
1586
1587 return handled;
1588}
1589
1590/*****************************************************************************/
1591
1592/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 * Initialize all the ports on a panel.
1594 */
1595
Jiri Slaby705c1862006-12-08 02:39:11 -08001596static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001598 struct stlport *portp;
1599 unsigned int i;
1600 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
Jiri Slabya0564e12006-12-08 02:38:37 -08001602 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
1604 chipmask = stl_panelinit(brdp, panelp);
1605
1606/*
1607 * All UART's are initialized (if found!). Now go through and setup
1608 * each ports data structures.
1609 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001610 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001611 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001612 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001614 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 break;
1616 }
Alan Coxd18a7502008-10-13 10:40:07 +01001617 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001618 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 portp->magic = STL_PORTMAGIC;
1620 portp->portnr = i;
1621 portp->brdnr = panelp->brdnr;
1622 portp->panelnr = panelp->panelnr;
1623 portp->uartp = panelp->uartp;
1624 portp->clk = brdp->clk;
1625 portp->baud_base = STL_BAUDBASE;
1626 portp->close_delay = STL_CLOSEDELAY;
1627 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001628 init_waitqueue_head(&portp->port.open_wait);
1629 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 portp->stats.brd = portp->brdnr;
1631 portp->stats.panel = portp->panelnr;
1632 portp->stats.port = portp->portnr;
1633 panelp->ports[i] = portp;
1634 stl_portinit(brdp, panelp, portp);
1635 }
1636
Jiri Slabyc62429d2006-12-08 02:39:14 -08001637 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638}
1639
Jiri Slaby3b85b342006-12-08 02:39:10 -08001640static void stl_cleanup_panels(struct stlbrd *brdp)
1641{
1642 struct stlpanel *panelp;
1643 struct stlport *portp;
1644 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001645 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001646
1647 for (j = 0; j < STL_MAXPANELS; j++) {
1648 panelp = brdp->panels[j];
1649 if (panelp == NULL)
1650 continue;
1651 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1652 portp = panelp->ports[k];
1653 if (portp == NULL)
1654 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001655 tty = tty_port_tty_get(&portp->port);
1656 if (tty != NULL) {
1657 stl_hangup(tty);
1658 tty_kref_put(tty);
1659 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001660 kfree(portp->tx.buf);
1661 kfree(portp);
1662 }
1663 kfree(panelp);
1664 }
1665}
1666
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667/*****************************************************************************/
1668
1669/*
1670 * Try to find and initialize an EasyIO board.
1671 */
1672
Jiri Slaby705c1862006-12-08 02:39:11 -08001673static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001675 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 unsigned int status;
1677 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001678 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Jiri Slabya0564e12006-12-08 02:38:37 -08001680 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 brdp->ioctrl = brdp->ioaddr1 + 1;
1683 brdp->iostatus = brdp->ioaddr1 + 2;
1684
1685 status = inb(brdp->iostatus);
1686 if ((status & EIO_IDBITMASK) == EIO_MK3)
1687 brdp->ioctrl++;
1688
1689/*
1690 * Handle board specific stuff now. The real difference is PCI
1691 * or not PCI.
1692 */
1693 if (brdp->brdtype == BRD_EASYIOPCI) {
1694 brdp->iosize1 = 0x80;
1695 brdp->iosize2 = 0x80;
1696 name = "serial(EIO-PCI)";
1697 outb(0x41, (brdp->ioaddr2 + 0x4c));
1698 } else {
1699 brdp->iosize1 = 8;
1700 name = "serial(EIO)";
1701 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1702 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1703 printk("STALLION: invalid irq=%d for brd=%d\n",
1704 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001705 retval = -EINVAL;
1706 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 }
1708 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1709 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1710 brdp->ioctrl);
1711 }
1712
Jiri Slaby3b85b342006-12-08 02:39:10 -08001713 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1715 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1716 "%x conflicts with another device\n", brdp->brdnr,
1717 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001718 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 }
1720
1721 if (brdp->iosize2 > 0)
1722 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1723 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1724 "address %x conflicts with another device\n",
1725 brdp->brdnr, brdp->ioaddr2);
1726 printk(KERN_WARNING "STALLION: Warning, also "
1727 "releasing board %d I/O address %x \n",
1728 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001729 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 }
1731
1732/*
1733 * Everything looks OK, so let's go ahead and probe for the hardware.
1734 */
1735 brdp->clk = CD1400_CLK;
1736 brdp->isr = stl_eiointr;
1737
Jiri Slaby3b85b342006-12-08 02:39:10 -08001738 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 switch (status & EIO_IDBITMASK) {
1740 case EIO_8PORTM:
1741 brdp->clk = CD1400_CLK8M;
1742 /* fall thru */
1743 case EIO_8PORTRS:
1744 case EIO_8PORTDI:
1745 brdp->nrports = 8;
1746 break;
1747 case EIO_4PORTRS:
1748 brdp->nrports = 4;
1749 break;
1750 case EIO_MK3:
1751 switch (status & EIO_BRDMASK) {
1752 case ID_BRD4:
1753 brdp->nrports = 4;
1754 break;
1755 case ID_BRD8:
1756 brdp->nrports = 8;
1757 break;
1758 case ID_BRD16:
1759 brdp->nrports = 16;
1760 break;
1761 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001762 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 }
1764 break;
1765 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001766 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 }
1768
1769/*
1770 * We have verified that the board is actually present, so now we
1771 * can complete the setup.
1772 */
1773
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001774 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001775 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001777 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001778 retval = -ENOMEM;
1779 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
1782 panelp->magic = STL_PANELMAGIC;
1783 panelp->brdnr = brdp->brdnr;
1784 panelp->panelnr = 0;
1785 panelp->nrports = brdp->nrports;
1786 panelp->iobase = brdp->ioaddr1;
1787 panelp->hwid = status;
1788 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001789 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 panelp->isr = stl_sc26198intr;
1791 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001792 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 panelp->isr = stl_cd1400eiointr;
1794 }
1795
1796 brdp->panels[0] = panelp;
1797 brdp->nrpanels = 1;
1798 brdp->state |= BRD_FOUND;
1799 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001800 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 printk("STALLION: failed to register interrupt "
1802 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001803 retval = -ENODEV;
1804 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001806
1807 return 0;
1808err_fr:
1809 stl_cleanup_panels(brdp);
1810err_rel2:
1811 if (brdp->iosize2 > 0)
1812 release_region(brdp->ioaddr2, brdp->iosize2);
1813err_rel1:
1814 release_region(brdp->ioaddr1, brdp->iosize1);
1815err:
1816 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817}
1818
1819/*****************************************************************************/
1820
1821/*
1822 * Try to find an ECH board and initialize it. This code is capable of
1823 * dealing with all types of ECH board.
1824 */
1825
Jiri Slaby705c1862006-12-08 02:39:11 -08001826static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001828 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001829 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1830 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 char *name;
1832
Jiri Slabya0564e12006-12-08 02:38:37 -08001833 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
1835 status = 0;
1836 conflict = 0;
1837
1838/*
1839 * Set up the initial board register contents for boards. This varies a
1840 * bit between the different board types. So we need to handle each
1841 * separately. Also do a check that the supplied IRQ is good.
1842 */
1843 switch (brdp->brdtype) {
1844
1845 case BRD_ECH:
1846 brdp->isr = stl_echatintr;
1847 brdp->ioctrl = brdp->ioaddr1 + 1;
1848 brdp->iostatus = brdp->ioaddr1 + 1;
1849 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001850 if ((status & ECH_IDBITMASK) != ECH_ID) {
1851 retval = -ENODEV;
1852 goto err;
1853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1855 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1856 printk("STALLION: invalid irq=%d for brd=%d\n",
1857 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001858 retval = -EINVAL;
1859 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 }
1861 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1862 status |= (stl_vecmap[brdp->irq] << 1);
1863 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1864 brdp->ioctrlval = ECH_INTENABLE |
1865 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001866 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1868 brdp->iosize1 = 2;
1869 brdp->iosize2 = 32;
1870 name = "serial(EC8/32)";
1871 outb(status, brdp->ioaddr1);
1872 break;
1873
1874 case BRD_ECHMC:
1875 brdp->isr = stl_echmcaintr;
1876 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1877 brdp->iostatus = brdp->ioctrl;
1878 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001879 if ((status & ECH_IDBITMASK) != ECH_ID) {
1880 retval = -ENODEV;
1881 goto err;
1882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1884 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1885 printk("STALLION: invalid irq=%d for brd=%d\n",
1886 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001887 retval = -EINVAL;
1888 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 }
1890 outb(ECHMC_BRDRESET, brdp->ioctrl);
1891 outb(ECHMC_INTENABLE, brdp->ioctrl);
1892 brdp->iosize1 = 64;
1893 name = "serial(EC8/32-MC)";
1894 break;
1895
1896 case BRD_ECHPCI:
1897 brdp->isr = stl_echpciintr;
1898 brdp->ioctrl = brdp->ioaddr1 + 2;
1899 brdp->iosize1 = 4;
1900 brdp->iosize2 = 8;
1901 name = "serial(EC8/32-PCI)";
1902 break;
1903
1904 case BRD_ECH64PCI:
1905 brdp->isr = stl_echpci64intr;
1906 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1907 outb(0x43, (brdp->ioaddr1 + 0x4c));
1908 brdp->iosize1 = 0x80;
1909 brdp->iosize2 = 0x80;
1910 name = "serial(EC8/64-PCI)";
1911 break;
1912
1913 default:
1914 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001915 retval = -EINVAL;
1916 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 }
1918
1919/*
1920 * Check boards for possible IO address conflicts and return fail status
1921 * if an IO conflict found.
1922 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001923 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1925 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1926 "%x conflicts with another device\n", brdp->brdnr,
1927 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001928 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 }
1930
1931 if (brdp->iosize2 > 0)
1932 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1933 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1934 "address %x conflicts with another device\n",
1935 brdp->brdnr, brdp->ioaddr2);
1936 printk(KERN_WARNING "STALLION: Warning, also "
1937 "releasing board %d I/O address %x \n",
1938 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001939 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 }
1941
1942/*
1943 * Scan through the secondary io address space looking for panels.
1944 * As we find'em allocate and initialize panel structures for each.
1945 */
1946 brdp->clk = CD1400_CLK;
1947 brdp->hwid = status;
1948
1949 ioaddr = brdp->ioaddr2;
1950 banknr = 0;
1951 panelnr = 0;
1952 nxtid = 0;
1953
Jiri Slabyc62429d2006-12-08 02:39:14 -08001954 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 if (brdp->brdtype == BRD_ECHPCI) {
1956 outb(nxtid, brdp->ioctrl);
1957 ioaddr = brdp->ioaddr2;
1958 }
1959 status = inb(ioaddr + ECH_PNLSTATUS);
1960 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07001961 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001962 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001963 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001965 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07001966 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001967 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 panelp->magic = STL_PANELMAGIC;
1970 panelp->brdnr = brdp->brdnr;
1971 panelp->panelnr = panelnr;
1972 panelp->iobase = ioaddr;
1973 panelp->pagenr = nxtid;
1974 panelp->hwid = status;
1975 brdp->bnk2panel[banknr] = panelp;
1976 brdp->bnkpageaddr[banknr] = nxtid;
1977 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
1978
1979 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001980 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 panelp->isr = stl_sc26198intr;
1982 if (status & ECH_PNL16PORT) {
1983 panelp->nrports = 16;
1984 brdp->bnk2panel[banknr] = panelp;
1985 brdp->bnkpageaddr[banknr] = nxtid;
1986 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
1987 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001988 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001991 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 panelp->isr = stl_cd1400echintr;
1993 if (status & ECH_PNL16PORT) {
1994 panelp->nrports = 16;
1995 panelp->ackmask = 0x80;
1996 if (brdp->brdtype != BRD_ECHPCI)
1997 ioaddr += EREG_BANKSIZE;
1998 brdp->bnk2panel[banknr] = panelp;
1999 brdp->bnkpageaddr[banknr] = ++nxtid;
2000 brdp->bnkstataddr[banknr++] = ioaddr +
2001 ECH_PNLSTATUS;
2002 } else {
2003 panelp->nrports = 8;
2004 panelp->ackmask = 0xc0;
2005 }
2006 }
2007
2008 nxtid++;
2009 ioaddr += EREG_BANKSIZE;
2010 brdp->nrports += panelp->nrports;
2011 brdp->panels[panelnr++] = panelp;
2012 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002013 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2014 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002015 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002016 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 }
2018
2019 brdp->nrpanels = panelnr;
2020 brdp->nrbnks = banknr;
2021 if (brdp->brdtype == BRD_ECH)
2022 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2023
2024 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002025 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 printk("STALLION: failed to register interrupt "
2027 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002028 retval = -ENODEV;
2029 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 }
2031
Jiri Slaby3b85b342006-12-08 02:39:10 -08002032 return 0;
2033err_fr:
2034 stl_cleanup_panels(brdp);
2035 if (brdp->iosize2 > 0)
2036 release_region(brdp->ioaddr2, brdp->iosize2);
2037err_rel1:
2038 release_region(brdp->ioaddr1, brdp->iosize1);
2039err:
2040 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041}
2042
2043/*****************************************************************************/
2044
2045/*
2046 * Initialize and configure the specified board.
2047 * Scan through all the boards in the configuration and see what we
2048 * can find. Handle EIO and the ECH boards a little differently here
2049 * since the initial search and setup is very different.
2050 */
2051
Jiri Slaby705c1862006-12-08 02:39:11 -08002052static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002054 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055
Jiri Slabya0564e12006-12-08 02:38:37 -08002056 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
2058 switch (brdp->brdtype) {
2059 case BRD_EASYIO:
2060 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002061 retval = stl_initeio(brdp);
2062 if (retval)
2063 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 break;
2065 case BRD_ECH:
2066 case BRD_ECHMC:
2067 case BRD_ECHPCI:
2068 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002069 retval = stl_initech(brdp);
2070 if (retval)
2071 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 break;
2073 default:
2074 printk("STALLION: board=%d is unknown board type=%d\n",
2075 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002076 retval = -ENODEV;
2077 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 }
2079
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 if ((brdp->state & BRD_FOUND) == 0) {
2081 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2082 stl_brdnames[brdp->brdtype], brdp->brdnr,
2083 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002084 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 }
2086
Jiri Slabyc62429d2006-12-08 02:39:14 -08002087 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002088 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 stl_initports(brdp, brdp->panels[i]);
2090
2091 printk("STALLION: %s found, board=%d io=%x irq=%d "
2092 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2093 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2094 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002095
2096 return 0;
2097err_free:
2098 free_irq(brdp->irq, brdp);
2099
2100 stl_cleanup_panels(brdp);
2101
2102 release_region(brdp->ioaddr1, brdp->iosize1);
2103 if (brdp->iosize2 > 0)
2104 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002105err:
2106 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107}
2108
2109/*****************************************************************************/
2110
2111/*
2112 * Find the next available board number that is free.
2113 */
2114
Jiri Slaby705c1862006-12-08 02:39:11 -08002115static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002117 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Jiri Slabyc62429d2006-12-08 02:39:14 -08002119 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002120 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 if (i >= stl_nrbrds)
2122 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002123 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002125
2126 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127}
2128
2129/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130/*
2131 * We have a Stallion board. Allocate a board structure and
2132 * initialize it. Read its IO and IRQ resources from PCI
2133 * configuration space.
2134 */
2135
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002136static int __devinit stl_pciprobe(struct pci_dev *pdev,
2137 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002139 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002140 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002141 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002143 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002144 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002145
Jiri Slaby3b85b342006-12-08 02:39:10 -08002146 retval = pci_enable_device(pdev);
2147 if (retval)
2148 goto err;
2149 brdp = stl_allocbrd();
2150 if (brdp == NULL) {
2151 retval = -ENOMEM;
2152 goto err;
2153 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002154 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002155 brdnr = stl_getbrdnr();
2156 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002157 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002159 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002160 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002161 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002163 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002164 stl_brds[brdp->brdnr] = brdp;
2165 mutex_unlock(&stl_brdslock);
2166
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002168 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
2170/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 * We have all resources from the board, so let's setup the actual
2172 * board structure now.
2173 */
2174 switch (brdtype) {
2175 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002176 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2177 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 break;
2179 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002180 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2181 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 break;
2183 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002184 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2185 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 break;
2187 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002188 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 break;
2190 }
2191
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002192 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002193 retval = stl_brdinit(brdp);
2194 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002195 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002197 pci_set_drvdata(pdev, brdp);
2198
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002199 for (i = 0; i < brdp->nrports; i++)
2200 tty_register_device(stl_serial,
2201 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2202
Jiri Slaby3b85b342006-12-08 02:39:10 -08002203 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002204err_null:
2205 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002206err_fr:
2207 kfree(brdp);
2208err:
2209 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210}
2211
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002212static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002214 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002215 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002217 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002219 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002221 release_region(brdp->ioaddr1, brdp->iosize1);
2222 if (brdp->iosize2 > 0)
2223 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002225 for (i = 0; i < brdp->nrports; i++)
2226 tty_unregister_device(stl_serial,
2227 brdp->brdnr * STL_MAXPORTS + i);
2228
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002229 stl_brds[brdp->brdnr] = NULL;
2230 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231}
2232
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002233static struct pci_driver stl_pcidriver = {
2234 .name = "stallion",
2235 .id_table = stl_pcibrds,
2236 .probe = stl_pciprobe,
2237 .remove = __devexit_p(stl_pciremove)
2238};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239
2240/*****************************************************************************/
2241
2242/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 * Return the board stats structure to user app.
2244 */
2245
2246static int stl_getbrdstats(combrd_t __user *bp)
2247{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002248 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002249 struct stlbrd *brdp;
2250 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002251 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
2253 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2254 return -EFAULT;
2255 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002256 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002258 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002259 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260
2261 memset(&stl_brdstats, 0, sizeof(combrd_t));
2262 stl_brdstats.brd = brdp->brdnr;
2263 stl_brdstats.type = brdp->brdtype;
2264 stl_brdstats.hwid = brdp->hwid;
2265 stl_brdstats.state = brdp->state;
2266 stl_brdstats.ioaddr = brdp->ioaddr1;
2267 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2268 stl_brdstats.irq = brdp->irq;
2269 stl_brdstats.nrpanels = brdp->nrpanels;
2270 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002271 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 panelp = brdp->panels[i];
2273 stl_brdstats.panels[i].panel = i;
2274 stl_brdstats.panels[i].hwid = panelp->hwid;
2275 stl_brdstats.panels[i].nrports = panelp->nrports;
2276 }
2277
2278 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2279}
2280
2281/*****************************************************************************/
2282
2283/*
2284 * Resolve the referenced port number into a port struct pointer.
2285 */
2286
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002287static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002289 struct stlbrd *brdp;
2290 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Jiri Slabyc62429d2006-12-08 02:39:14 -08002292 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2293 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002295 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002296 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002297 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002298 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002300 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002301 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002302 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002303 return NULL;
2304 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305}
2306
2307/*****************************************************************************/
2308
2309/*
2310 * Return the port stats structure to user app. A NULL port struct
2311 * pointer passed in means that we need to find out from the app
2312 * what port to get stats for (used through board control device).
2313 */
2314
Alan Coxd18a7502008-10-13 10:40:07 +01002315static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002317 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 unsigned char *head, *tail;
2319 unsigned long flags;
2320
2321 if (!portp) {
2322 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2323 return -EFAULT;
2324 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2325 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002326 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002327 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
2329
2330 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002331 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 portp->stats.hwid = portp->hwid;
2333
2334 portp->stats.ttystate = 0;
2335 portp->stats.cflags = 0;
2336 portp->stats.iflags = 0;
2337 portp->stats.oflags = 0;
2338 portp->stats.lflags = 0;
2339 portp->stats.rxbuffered = 0;
2340
Alan Coxb65b5b52006-06-27 02:54:05 -07002341 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002342 if (tty != NULL && portp->port.tty == tty) {
2343 portp->stats.ttystate = tty->flags;
2344 /* No longer available as a statistic */
2345 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2346 if (tty->termios != NULL) {
2347 portp->stats.cflags = tty->termios->c_cflag;
2348 portp->stats.iflags = tty->termios->c_iflag;
2349 portp->stats.oflags = tty->termios->c_oflag;
2350 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 }
Alan Coxd18a7502008-10-13 10:40:07 +01002352 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002353 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
2355 head = portp->tx.head;
2356 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002357 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2358 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
2360 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2361
2362 return copy_to_user(cp, &portp->stats,
2363 sizeof(comstats_t)) ? -EFAULT : 0;
2364}
2365
2366/*****************************************************************************/
2367
2368/*
2369 * Clear the port stats structure. We also return it zeroed out...
2370 */
2371
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002372static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002374 comstats_t stl_comstats;
2375
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 if (!portp) {
2377 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2378 return -EFAULT;
2379 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2380 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002381 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002382 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 }
2384
2385 memset(&portp->stats, 0, sizeof(comstats_t));
2386 portp->stats.brd = portp->brdnr;
2387 portp->stats.panel = portp->panelnr;
2388 portp->stats.port = portp->portnr;
2389 return copy_to_user(cp, &portp->stats,
2390 sizeof(comstats_t)) ? -EFAULT : 0;
2391}
2392
2393/*****************************************************************************/
2394
2395/*
2396 * Return the entire driver ports structure to a user app.
2397 */
2398
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002399static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002401 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002402 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002404 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 return -EFAULT;
2406 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2407 stl_dummyport.portnr);
2408 if (!portp)
2409 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002410 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411}
2412
2413/*****************************************************************************/
2414
2415/*
2416 * Return the entire driver board structure to a user app.
2417 */
2418
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002419static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002421 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002422 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002424 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002426 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 return -ENODEV;
2428 brdp = stl_brds[stl_dummybrd.brdnr];
2429 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002430 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002431 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432}
2433
2434/*****************************************************************************/
2435
2436/*
2437 * The "staliomem" device is also required to do some special operations
2438 * on the board and/or ports. In this driver it is mostly used for stats
2439 * collection.
2440 */
2441
Alan Cox894cb912009-10-13 16:34:15 +01002442static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443{
2444 int brdnr, rc;
2445 void __user *argp = (void __user *)arg;
2446
Alan Cox894cb912009-10-13 16:34:15 +01002447 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448
Alan Cox894cb912009-10-13 16:34:15 +01002449 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002451 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 rc = 0;
2453
Alan Cox894cb912009-10-13 16:34:15 +01002454 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 switch (cmd) {
2456 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002457 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 break;
2459 case COM_CLRPORTSTATS:
2460 rc = stl_clrportstats(NULL, argp);
2461 break;
2462 case COM_GETBRDSTATS:
2463 rc = stl_getbrdstats(argp);
2464 break;
2465 case COM_READPORT:
2466 rc = stl_getportstruct(argp);
2467 break;
2468 case COM_READBOARD:
2469 rc = stl_getbrdstruct(argp);
2470 break;
2471 default:
2472 rc = -ENOIOCTLCMD;
2473 break;
2474 }
Alan Cox894cb912009-10-13 16:34:15 +01002475 unlock_kernel();
Jiri Slabyc62429d2006-12-08 02:39:14 -08002476 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477}
2478
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002479static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 .open = stl_open,
2481 .close = stl_close,
2482 .write = stl_write,
2483 .put_char = stl_putchar,
2484 .flush_chars = stl_flushchars,
2485 .write_room = stl_writeroom,
2486 .chars_in_buffer = stl_charsinbuffer,
2487 .ioctl = stl_ioctl,
2488 .set_termios = stl_settermios,
2489 .throttle = stl_throttle,
2490 .unthrottle = stl_unthrottle,
2491 .stop = stl_stop,
2492 .start = stl_start,
2493 .hangup = stl_hangup,
2494 .flush_buffer = stl_flushbuffer,
2495 .break_ctl = stl_breakctl,
2496 .wait_until_sent = stl_waituntilsent,
2497 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 .tiocmget = stl_tiocmget,
2499 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002500 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501};
2502
Alan Cox31f35932009-01-02 13:45:05 +00002503static const struct tty_port_operations stl_port_ops = {
2504 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002505 .dtr_rts = stl_dtr_rts,
Alan Cox047e9652009-11-30 13:17:03 +00002506 .activate = stl_activate,
2507 .shutdown = stl_shutdown,
Alan Cox31f35932009-01-02 13:45:05 +00002508};
2509
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511/* CD1400 HARDWARE FUNCTIONS */
2512/*****************************************************************************/
2513
2514/*
2515 * These functions get/set/update the registers of the cd1400 UARTs.
2516 * Access to the cd1400 registers is via an address/data io port pair.
2517 * (Maybe should make this inline...)
2518 */
2519
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002520static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521{
2522 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002523 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524}
2525
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002526static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002528 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 outb(value, portp->ioaddr + EREG_DATA);
2530}
2531
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002532static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002534 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 if (inb(portp->ioaddr + EREG_DATA) != value) {
2536 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002537 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002539 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540}
2541
2542/*****************************************************************************/
2543
2544/*
2545 * Inbitialize the UARTs in a panel. We don't care what sort of board
2546 * these ports are on - since the port io registers are almost
2547 * identical when dealing with ports.
2548 */
2549
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002550static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551{
2552 unsigned int gfrcr;
2553 int chipmask, i, j;
2554 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002555 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
Jiri Slabya0564e12006-12-08 02:38:37 -08002557 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Alan Coxb65b5b52006-06-27 02:54:05 -07002559 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 BRDENABLE(panelp->brdnr, panelp->pagenr);
2561
2562/*
2563 * Check that each chip is present and started up OK.
2564 */
2565 chipmask = 0;
2566 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002567 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 if (brdp->brdtype == BRD_ECHPCI) {
2569 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2570 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002571 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 uartaddr = (i & 0x01) ? 0x080 : 0;
2574 outb((GFRCR + uartaddr), ioaddr);
2575 outb(0, (ioaddr + EREG_DATA));
2576 outb((CCR + uartaddr), ioaddr);
2577 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2578 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2579 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002580 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2582 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2585 printk("STALLION: cd1400 not responding, "
2586 "brd=%d panel=%d chip=%d\n",
2587 panelp->brdnr, panelp->panelnr, i);
2588 continue;
2589 }
2590 chipmask |= (0x1 << i);
2591 outb((PPR + uartaddr), ioaddr);
2592 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2593 }
2594
2595 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002596 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002597 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598}
2599
2600/*****************************************************************************/
2601
2602/*
2603 * Initialize hardware specific port registers.
2604 */
2605
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002606static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607{
Alan Coxb65b5b52006-06-27 02:54:05 -07002608 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002609 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2610 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Jiri Slaby615e4a72006-12-08 02:38:38 -08002612 if ((brdp == NULL) || (panelp == NULL) ||
2613 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 return;
2615
Alan Coxb65b5b52006-06-27 02:54:05 -07002616 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2618 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2619 portp->uartaddr = (portp->portnr & 0x04) << 5;
2620 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2621
2622 BRDENABLE(portp->brdnr, portp->pagenr);
2623 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2624 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2625 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2626 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002627 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628}
2629
2630/*****************************************************************************/
2631
2632/*
2633 * Wait for the command register to be ready. We will poll this,
2634 * since it won't usually take too long to be ready.
2635 */
2636
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002637static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638{
2639 int i;
2640
Jiri Slabyc62429d2006-12-08 02:39:14 -08002641 for (i = 0; i < CCR_MAXWAIT; i++)
2642 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
2645 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2646 portp->portnr, portp->panelnr, portp->brdnr);
2647}
2648
2649/*****************************************************************************/
2650
2651/*
2652 * Set up the cd1400 registers for a port based on the termios port
2653 * settings.
2654 */
2655
Alan Cox606d0992006-12-08 02:38:45 -08002656static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002658 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 unsigned long flags;
2660 unsigned int clkdiv, baudrate;
2661 unsigned char cor1, cor2, cor3;
2662 unsigned char cor4, cor5, ccr;
2663 unsigned char srer, sreron, sreroff;
2664 unsigned char mcor1, mcor2, rtpr;
2665 unsigned char clk, div;
2666
2667 cor1 = 0;
2668 cor2 = 0;
2669 cor3 = 0;
2670 cor4 = 0;
2671 cor5 = 0;
2672 ccr = 0;
2673 rtpr = 0;
2674 clk = 0;
2675 div = 0;
2676 mcor1 = 0;
2677 mcor2 = 0;
2678 sreron = 0;
2679 sreroff = 0;
2680
2681 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002682 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 return;
2684
2685/*
2686 * Set up the RX char ignore mask with those RX error types we
2687 * can ignore. We can get the cd1400 to help us out a little here,
2688 * it will ignore parity errors and breaks for us.
2689 */
2690 portp->rxignoremsk = 0;
2691 if (tiosp->c_iflag & IGNPAR) {
2692 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2693 cor1 |= COR1_PARIGNORE;
2694 }
2695 if (tiosp->c_iflag & IGNBRK) {
2696 portp->rxignoremsk |= ST_BREAK;
2697 cor4 |= COR4_IGNBRK;
2698 }
2699
2700 portp->rxmarkmsk = ST_OVERRUN;
2701 if (tiosp->c_iflag & (INPCK | PARMRK))
2702 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2703 if (tiosp->c_iflag & BRKINT)
2704 portp->rxmarkmsk |= ST_BREAK;
2705
2706/*
2707 * Go through the char size, parity and stop bits and set all the
2708 * option register appropriately.
2709 */
2710 switch (tiosp->c_cflag & CSIZE) {
2711 case CS5:
2712 cor1 |= COR1_CHL5;
2713 break;
2714 case CS6:
2715 cor1 |= COR1_CHL6;
2716 break;
2717 case CS7:
2718 cor1 |= COR1_CHL7;
2719 break;
2720 default:
2721 cor1 |= COR1_CHL8;
2722 break;
2723 }
2724
2725 if (tiosp->c_cflag & CSTOPB)
2726 cor1 |= COR1_STOP2;
2727 else
2728 cor1 |= COR1_STOP1;
2729
2730 if (tiosp->c_cflag & PARENB) {
2731 if (tiosp->c_cflag & PARODD)
2732 cor1 |= (COR1_PARENB | COR1_PARODD);
2733 else
2734 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2735 } else {
2736 cor1 |= COR1_PARNONE;
2737 }
2738
2739/*
2740 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2741 * space for hardware flow control and the like. This should be set to
2742 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2743 * really be based on VTIME.
2744 */
2745 cor3 |= FIFO_RXTHRESHOLD;
2746 rtpr = 2;
2747
2748/*
2749 * Calculate the baud rate timers. For now we will just assume that
2750 * the input and output baud are the same. Could have used a baud
2751 * table here, but this way we can generate virtually any baud rate
2752 * we like!
2753 */
2754 baudrate = tiosp->c_cflag & CBAUD;
2755 if (baudrate & CBAUDEX) {
2756 baudrate &= ~CBAUDEX;
2757 if ((baudrate < 1) || (baudrate > 4))
2758 tiosp->c_cflag &= ~CBAUDEX;
2759 else
2760 baudrate += 15;
2761 }
2762 baudrate = stl_baudrates[baudrate];
2763 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002764 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002766 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002768 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002770 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002772 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 baudrate = (portp->baud_base / portp->custom_divisor);
2774 }
2775 if (baudrate > STL_CD1400MAXBAUD)
2776 baudrate = STL_CD1400MAXBAUD;
2777
2778 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002779 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2780 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 if (clkdiv < 0x100)
2782 break;
2783 }
2784 div = (unsigned char) clkdiv;
2785 }
2786
2787/*
2788 * Check what form of modem signaling is required and set it up.
2789 */
2790 if ((tiosp->c_cflag & CLOCAL) == 0) {
2791 mcor1 |= MCOR1_DCD;
2792 mcor2 |= MCOR2_DCD;
2793 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002794 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002795 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002796 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798/*
2799 * Setup cd1400 enhanced modes if we can. In particular we want to
2800 * handle as much of the flow control as possible automatically. As
2801 * well as saving a few CPU cycles it will also greatly improve flow
2802 * control reliability.
2803 */
2804 if (tiosp->c_iflag & IXON) {
2805 cor2 |= COR2_TXIBE;
2806 cor3 |= COR3_SCD12;
2807 if (tiosp->c_iflag & IXANY)
2808 cor2 |= COR2_IXM;
2809 }
2810
2811 if (tiosp->c_cflag & CRTSCTS) {
2812 cor2 |= COR2_CTSAE;
2813 mcor1 |= FIFO_RTSTHRESHOLD;
2814 }
2815
2816/*
2817 * All cd1400 register values calculated so go through and set
2818 * them all up.
2819 */
2820
Jiri Slabya0564e12006-12-08 02:38:37 -08002821 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002823 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002825 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002827 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2828 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2830 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831
Alan Coxb65b5b52006-06-27 02:54:05 -07002832 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 BRDENABLE(portp->brdnr, portp->pagenr);
2834 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2835 srer = stl_cd1400getreg(portp, SRER);
2836 stl_cd1400setreg(portp, SRER, 0);
2837 if (stl_cd1400updatereg(portp, COR1, cor1))
2838 ccr = 1;
2839 if (stl_cd1400updatereg(portp, COR2, cor2))
2840 ccr = 1;
2841 if (stl_cd1400updatereg(portp, COR3, cor3))
2842 ccr = 1;
2843 if (ccr) {
2844 stl_cd1400ccrwait(portp);
2845 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2846 }
2847 stl_cd1400setreg(portp, COR4, cor4);
2848 stl_cd1400setreg(portp, COR5, cor5);
2849 stl_cd1400setreg(portp, MCOR1, mcor1);
2850 stl_cd1400setreg(portp, MCOR2, mcor2);
2851 if (baudrate > 0) {
2852 stl_cd1400setreg(portp, TCOR, clk);
2853 stl_cd1400setreg(portp, TBPR, div);
2854 stl_cd1400setreg(portp, RCOR, clk);
2855 stl_cd1400setreg(portp, RBPR, div);
2856 }
2857 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2858 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2859 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2860 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2861 stl_cd1400setreg(portp, RTPR, rtpr);
2862 mcor1 = stl_cd1400getreg(portp, MSVR1);
2863 if (mcor1 & MSVR1_DCD)
2864 portp->sigs |= TIOCM_CD;
2865 else
2866 portp->sigs &= ~TIOCM_CD;
2867 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2868 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002869 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870}
2871
2872/*****************************************************************************/
2873
2874/*
2875 * Set the state of the DTR and RTS signals.
2876 */
2877
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002878static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879{
2880 unsigned char msvr1, msvr2;
2881 unsigned long flags;
2882
Jiri Slabya0564e12006-12-08 02:38:37 -08002883 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2884 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885
2886 msvr1 = 0;
2887 msvr2 = 0;
2888 if (dtr > 0)
2889 msvr1 = MSVR1_DTR;
2890 if (rts > 0)
2891 msvr2 = MSVR2_RTS;
2892
Alan Coxb65b5b52006-06-27 02:54:05 -07002893 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 BRDENABLE(portp->brdnr, portp->pagenr);
2895 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2896 if (rts >= 0)
2897 stl_cd1400setreg(portp, MSVR2, msvr2);
2898 if (dtr >= 0)
2899 stl_cd1400setreg(portp, MSVR1, msvr1);
2900 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002901 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902}
2903
2904/*****************************************************************************/
2905
2906/*
2907 * Return the state of the signals.
2908 */
2909
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002910static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911{
2912 unsigned char msvr1, msvr2;
2913 unsigned long flags;
2914 int sigs;
2915
Jiri Slabya0564e12006-12-08 02:38:37 -08002916 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
Alan Coxb65b5b52006-06-27 02:54:05 -07002918 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 BRDENABLE(portp->brdnr, portp->pagenr);
2920 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2921 msvr1 = stl_cd1400getreg(portp, MSVR1);
2922 msvr2 = stl_cd1400getreg(portp, MSVR2);
2923 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002924 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
2926 sigs = 0;
2927 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2928 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2929 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2930 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2931#if 0
2932 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2933 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2934#else
2935 sigs |= TIOCM_DSR;
2936#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002937 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938}
2939
2940/*****************************************************************************/
2941
2942/*
2943 * Enable/Disable the Transmitter and/or Receiver.
2944 */
2945
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002946static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947{
2948 unsigned char ccr;
2949 unsigned long flags;
2950
Jiri Slabya0564e12006-12-08 02:38:37 -08002951 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2952
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 ccr = 0;
2954
2955 if (tx == 0)
2956 ccr |= CCR_TXDISABLE;
2957 else if (tx > 0)
2958 ccr |= CCR_TXENABLE;
2959 if (rx == 0)
2960 ccr |= CCR_RXDISABLE;
2961 else if (rx > 0)
2962 ccr |= CCR_RXENABLE;
2963
Alan Coxb65b5b52006-06-27 02:54:05 -07002964 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 BRDENABLE(portp->brdnr, portp->pagenr);
2966 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2967 stl_cd1400ccrwait(portp);
2968 stl_cd1400setreg(portp, CCR, ccr);
2969 stl_cd1400ccrwait(portp);
2970 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002971 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972}
2973
2974/*****************************************************************************/
2975
2976/*
2977 * Start/stop the Transmitter and/or Receiver.
2978 */
2979
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002980static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981{
2982 unsigned char sreron, sreroff;
2983 unsigned long flags;
2984
Jiri Slabya0564e12006-12-08 02:38:37 -08002985 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986
2987 sreron = 0;
2988 sreroff = 0;
2989 if (tx == 0)
2990 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
2991 else if (tx == 1)
2992 sreron |= SRER_TXDATA;
2993 else if (tx >= 2)
2994 sreron |= SRER_TXEMPTY;
2995 if (rx == 0)
2996 sreroff |= SRER_RXDATA;
2997 else if (rx > 0)
2998 sreron |= SRER_RXDATA;
2999
Alan Coxb65b5b52006-06-27 02:54:05 -07003000 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 BRDENABLE(portp->brdnr, portp->pagenr);
3002 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3003 stl_cd1400setreg(portp, SRER,
3004 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3005 BRDDISABLE(portp->brdnr);
3006 if (tx > 0)
3007 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003008 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009}
3010
3011/*****************************************************************************/
3012
3013/*
3014 * Disable all interrupts from this port.
3015 */
3016
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003017static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018{
3019 unsigned long flags;
3020
Jiri Slabya0564e12006-12-08 02:38:37 -08003021 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3022
Alan Coxb65b5b52006-06-27 02:54:05 -07003023 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 BRDENABLE(portp->brdnr, portp->pagenr);
3025 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3026 stl_cd1400setreg(portp, SRER, 0);
3027 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003028 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029}
3030
3031/*****************************************************************************/
3032
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003033static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034{
3035 unsigned long flags;
3036
Jiri Slabya0564e12006-12-08 02:38:37 -08003037 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038
Alan Coxb65b5b52006-06-27 02:54:05 -07003039 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 BRDENABLE(portp->brdnr, portp->pagenr);
3041 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3042 stl_cd1400setreg(portp, SRER,
3043 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3044 SRER_TXEMPTY));
3045 BRDDISABLE(portp->brdnr);
3046 portp->brklen = len;
3047 if (len == 1)
3048 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003049 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050}
3051
3052/*****************************************************************************/
3053
3054/*
3055 * Take flow control actions...
3056 */
3057
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003058static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
3060 struct tty_struct *tty;
3061 unsigned long flags;
3062
Jiri Slabya0564e12006-12-08 02:38:37 -08003063 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Jiri Slaby615e4a72006-12-08 02:38:38 -08003065 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003067 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003068 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 return;
3070
Alan Coxb65b5b52006-06-27 02:54:05 -07003071 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 BRDENABLE(portp->brdnr, portp->pagenr);
3073 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3074
3075 if (state) {
3076 if (tty->termios->c_iflag & IXOFF) {
3077 stl_cd1400ccrwait(portp);
3078 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3079 portp->stats.rxxon++;
3080 stl_cd1400ccrwait(portp);
3081 }
3082/*
3083 * Question: should we return RTS to what it was before? It may
3084 * have been set by an ioctl... Suppose not, since if you have
3085 * hardware flow control set then it is pretty silly to go and
3086 * set the RTS line by hand.
3087 */
3088 if (tty->termios->c_cflag & CRTSCTS) {
3089 stl_cd1400setreg(portp, MCOR1,
3090 (stl_cd1400getreg(portp, MCOR1) |
3091 FIFO_RTSTHRESHOLD));
3092 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3093 portp->stats.rxrtson++;
3094 }
3095 } else {
3096 if (tty->termios->c_iflag & IXOFF) {
3097 stl_cd1400ccrwait(portp);
3098 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3099 portp->stats.rxxoff++;
3100 stl_cd1400ccrwait(portp);
3101 }
3102 if (tty->termios->c_cflag & CRTSCTS) {
3103 stl_cd1400setreg(portp, MCOR1,
3104 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3105 stl_cd1400setreg(portp, MSVR2, 0);
3106 portp->stats.rxrtsoff++;
3107 }
3108 }
3109
3110 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003111 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003112 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113}
3114
3115/*****************************************************************************/
3116
3117/*
3118 * Send a flow control character...
3119 */
3120
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003121static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122{
3123 struct tty_struct *tty;
3124 unsigned long flags;
3125
Jiri Slabya0564e12006-12-08 02:38:37 -08003126 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
Jiri Slaby615e4a72006-12-08 02:38:38 -08003128 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003130 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003131 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 return;
3133
Alan Coxb65b5b52006-06-27 02:54:05 -07003134 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 BRDENABLE(portp->brdnr, portp->pagenr);
3136 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3137 if (state) {
3138 stl_cd1400ccrwait(portp);
3139 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3140 portp->stats.rxxon++;
3141 stl_cd1400ccrwait(portp);
3142 } else {
3143 stl_cd1400ccrwait(portp);
3144 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3145 portp->stats.rxxoff++;
3146 stl_cd1400ccrwait(portp);
3147 }
3148 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003149 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003150 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151}
3152
3153/*****************************************************************************/
3154
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003155static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156{
3157 unsigned long flags;
3158
Jiri Slabya0564e12006-12-08 02:38:37 -08003159 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160
Jiri Slaby615e4a72006-12-08 02:38:38 -08003161 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 return;
3163
Alan Coxb65b5b52006-06-27 02:54:05 -07003164 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 BRDENABLE(portp->brdnr, portp->pagenr);
3166 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3167 stl_cd1400ccrwait(portp);
3168 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3169 stl_cd1400ccrwait(portp);
3170 portp->tx.tail = portp->tx.head;
3171 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003172 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173}
3174
3175/*****************************************************************************/
3176
3177/*
3178 * Return the current state of data flow on this port. This is only
3179 * really interresting when determining if data has fully completed
3180 * transmission or not... This is easy for the cd1400, it accurately
3181 * maintains the busy port flag.
3182 */
3183
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003184static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185{
Jiri Slabya0564e12006-12-08 02:38:37 -08003186 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Jiri Slaby615e4a72006-12-08 02:38:38 -08003188 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003189 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Jesper Juhl014c2542006-01-15 02:37:08 +01003191 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192}
3193
3194/*****************************************************************************/
3195
3196/*
3197 * Interrupt service routine for cd1400 EasyIO boards.
3198 */
3199
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003200static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201{
3202 unsigned char svrtype;
3203
Jiri Slabya0564e12006-12-08 02:38:37 -08003204 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
Alan Coxb65b5b52006-06-27 02:54:05 -07003206 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 outb(SVRR, iobase);
3208 svrtype = inb(iobase + EREG_DATA);
3209 if (panelp->nrports > 4) {
3210 outb((SVRR + 0x80), iobase);
3211 svrtype |= inb(iobase + EREG_DATA);
3212 }
3213
3214 if (svrtype & SVRR_RX)
3215 stl_cd1400rxisr(panelp, iobase);
3216 else if (svrtype & SVRR_TX)
3217 stl_cd1400txisr(panelp, iobase);
3218 else if (svrtype & SVRR_MDM)
3219 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003220
3221 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222}
3223
3224/*****************************************************************************/
3225
3226/*
3227 * Interrupt service routine for cd1400 panels.
3228 */
3229
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003230static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231{
3232 unsigned char svrtype;
3233
Jiri Slabya0564e12006-12-08 02:38:37 -08003234 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235
3236 outb(SVRR, iobase);
3237 svrtype = inb(iobase + EREG_DATA);
3238 outb((SVRR + 0x80), iobase);
3239 svrtype |= inb(iobase + EREG_DATA);
3240 if (svrtype & SVRR_RX)
3241 stl_cd1400rxisr(panelp, iobase);
3242 else if (svrtype & SVRR_TX)
3243 stl_cd1400txisr(panelp, iobase);
3244 else if (svrtype & SVRR_MDM)
3245 stl_cd1400mdmisr(panelp, iobase);
3246}
3247
3248
3249/*****************************************************************************/
3250
3251/*
3252 * Unfortunately we need to handle breaks in the TX data stream, since
3253 * this is the only way to generate them on the cd1400.
3254 */
3255
Jiri Slaby60be4812006-12-08 02:38:40 -08003256static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257{
3258 if (portp->brklen == 1) {
3259 outb((COR2 + portp->uartaddr), ioaddr);
3260 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3261 (ioaddr + EREG_DATA));
3262 outb((TDR + portp->uartaddr), ioaddr);
3263 outb(ETC_CMD, (ioaddr + EREG_DATA));
3264 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3265 outb((SRER + portp->uartaddr), ioaddr);
3266 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3267 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003268 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 } else if (portp->brklen > 1) {
3270 outb((TDR + portp->uartaddr), ioaddr);
3271 outb(ETC_CMD, (ioaddr + EREG_DATA));
3272 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3273 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003274 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 } else {
3276 outb((COR2 + portp->uartaddr), ioaddr);
3277 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3278 (ioaddr + EREG_DATA));
3279 portp->brklen = 0;
3280 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003281 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282}
3283
3284/*****************************************************************************/
3285
3286/*
3287 * Transmit interrupt handler. This has gotta be fast! Handling TX
3288 * chars is pretty simple, stuff as many as possible from the TX buffer
3289 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3290 * are embedded as commands in the data stream. Oh no, had to use a goto!
3291 * This could be optimized more, will do when I get time...
3292 * In practice it is possible that interrupts are enabled but that the
3293 * port has been hung up. Need to handle not having any TX buffer here,
3294 * this is done by using the side effect that head and tail will also
3295 * be NULL if the buffer has been freed.
3296 */
3297
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003298static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003300 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301 int len, stlen;
3302 char *head, *tail;
3303 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003304 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Jiri Slabya0564e12006-12-08 02:38:37 -08003306 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307
3308 ioack = inb(ioaddr + EREG_TXACK);
3309 if (((ioack & panelp->ackmask) != 0) ||
3310 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3311 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3312 return;
3313 }
3314 portp = panelp->ports[(ioack >> 3)];
3315
3316/*
3317 * Unfortunately we need to handle breaks in the data stream, since
3318 * this is the only way to generate them on the cd1400. Do it now if
3319 * a break is to be sent.
3320 */
3321 if (portp->brklen != 0)
3322 if (stl_cd1400breakisr(portp, ioaddr))
3323 goto stl_txalldone;
3324
3325 head = portp->tx.head;
3326 tail = portp->tx.tail;
3327 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3328 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3329 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3330 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003331 tty = tty_port_tty_get(&portp->port);
3332 if (tty) {
3333 tty_wakeup(tty);
3334 tty_kref_put(tty);
3335 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 }
3337
3338 if (len == 0) {
3339 outb((SRER + portp->uartaddr), ioaddr);
3340 srer = inb(ioaddr + EREG_DATA);
3341 if (srer & SRER_TXDATA) {
3342 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3343 } else {
3344 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3345 clear_bit(ASYI_TXBUSY, &portp->istate);
3346 }
3347 outb(srer, (ioaddr + EREG_DATA));
3348 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003349 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003351 stlen = min_t(unsigned int, len,
3352 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 outb((TDR + portp->uartaddr), ioaddr);
3354 outsb((ioaddr + EREG_DATA), tail, stlen);
3355 len -= stlen;
3356 tail += stlen;
3357 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3358 tail = portp->tx.buf;
3359 if (len > 0) {
3360 outsb((ioaddr + EREG_DATA), tail, len);
3361 tail += len;
3362 }
3363 portp->tx.tail = tail;
3364 }
3365
3366stl_txalldone:
3367 outb((EOSRR + portp->uartaddr), ioaddr);
3368 outb(0, (ioaddr + EREG_DATA));
3369}
3370
3371/*****************************************************************************/
3372
3373/*
3374 * Receive character interrupt handler. Determine if we have good chars
3375 * or bad chars and then process appropriately. Good chars are easy
3376 * just shove the lot into the RX buffer and set all status byte to 0.
3377 * If a bad RX char then process as required. This routine needs to be
3378 * fast! In practice it is possible that we get an interrupt on a port
3379 * that is closed. This can happen on hangups - since they completely
3380 * shutdown a port not in user context. Need to handle this case.
3381 */
3382
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003383static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003385 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 struct tty_struct *tty;
3387 unsigned int ioack, len, buflen;
3388 unsigned char status;
3389 char ch;
3390
Jiri Slabya0564e12006-12-08 02:38:37 -08003391 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
3393 ioack = inb(ioaddr + EREG_RXACK);
3394 if ((ioack & panelp->ackmask) != 0) {
3395 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3396 return;
3397 }
3398 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003399 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
3401 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3402 outb((RDCR + portp->uartaddr), ioaddr);
3403 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003404 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003405 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406 outb((RDSR + portp->uartaddr), ioaddr);
3407 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3408 portp->stats.rxlost += len;
3409 portp->stats.rxtotal += len;
3410 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003411 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003413 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003415 tty_prepare_flip_string(tty, &ptr, len);
3416 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 tty_schedule_flip(tty);
3418 portp->stats.rxtotal += len;
3419 }
3420 }
3421 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3422 outb((RDSR + portp->uartaddr), ioaddr);
3423 status = inb(ioaddr + EREG_DATA);
3424 ch = inb(ioaddr + EREG_DATA);
3425 if (status & ST_PARITY)
3426 portp->stats.rxparity++;
3427 if (status & ST_FRAMING)
3428 portp->stats.rxframing++;
3429 if (status & ST_OVERRUN)
3430 portp->stats.rxoverrun++;
3431 if (status & ST_BREAK)
3432 portp->stats.rxbreaks++;
3433 if (status & ST_SCHARMASK) {
3434 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3435 portp->stats.txxon++;
3436 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3437 portp->stats.txxoff++;
3438 goto stl_rxalldone;
3439 }
Alan Cox33f0f882006-01-09 20:54:13 -08003440 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 if (portp->rxmarkmsk & status) {
3442 if (status & ST_BREAK) {
3443 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003444 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 do_SAK(tty);
3446 BRDENABLE(portp->brdnr, portp->pagenr);
3447 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003448 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003450 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003452 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003454 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003456 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003458 tty_insert_flip_char(tty, ch, status);
3459 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 }
3461 } else {
3462 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003463 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 return;
3465 }
3466
3467stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003468 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 outb((EOSRR + portp->uartaddr), ioaddr);
3470 outb(0, (ioaddr + EREG_DATA));
3471}
3472
3473/*****************************************************************************/
3474
3475/*
3476 * Modem interrupt handler. The is called when the modem signal line
3477 * (DCD) has changed state. Leave most of the work to the off-level
3478 * processing routine.
3479 */
3480
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003481static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003483 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 unsigned int ioack;
3485 unsigned char misr;
3486
Jiri Slabya0564e12006-12-08 02:38:37 -08003487 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
3489 ioack = inb(ioaddr + EREG_MDACK);
3490 if (((ioack & panelp->ackmask) != 0) ||
3491 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3492 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3493 return;
3494 }
3495 portp = panelp->ports[(ioack >> 3)];
3496
3497 outb((MISR + portp->uartaddr), ioaddr);
3498 misr = inb(ioaddr + EREG_DATA);
3499 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003500 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 portp->stats.modem++;
3502 }
3503
3504 outb((EOSRR + portp->uartaddr), ioaddr);
3505 outb(0, (ioaddr + EREG_DATA));
3506}
3507
3508/*****************************************************************************/
3509/* SC26198 HARDWARE FUNCTIONS */
3510/*****************************************************************************/
3511
3512/*
3513 * These functions get/set/update the registers of the sc26198 UARTs.
3514 * Access to the sc26198 registers is via an address/data io port pair.
3515 * (Maybe should make this inline...)
3516 */
3517
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003518static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519{
3520 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003521 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522}
3523
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003524static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525{
3526 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3527 outb(value, (portp->ioaddr + XP_DATA));
3528}
3529
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003530static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531{
3532 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3533 if (inb(portp->ioaddr + XP_DATA) != value) {
3534 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003535 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003537 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538}
3539
3540/*****************************************************************************/
3541
3542/*
3543 * Functions to get and set the sc26198 global registers.
3544 */
3545
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003546static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547{
3548 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003549 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550}
3551
3552#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003553static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554{
3555 outb(regnr, (portp->ioaddr + XP_ADDR));
3556 outb(value, (portp->ioaddr + XP_DATA));
3557}
3558#endif
3559
3560/*****************************************************************************/
3561
3562/*
3563 * Inbitialize the UARTs in a panel. We don't care what sort of board
3564 * these ports are on - since the port io registers are almost
3565 * identical when dealing with ports.
3566 */
3567
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003568static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569{
3570 int chipmask, i;
3571 int nrchips, ioaddr;
3572
Jiri Slabya0564e12006-12-08 02:38:37 -08003573 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574
3575 BRDENABLE(panelp->brdnr, panelp->pagenr);
3576
3577/*
3578 * Check that each chip is present and started up OK.
3579 */
3580 chipmask = 0;
3581 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3582 if (brdp->brdtype == BRD_ECHPCI)
3583 outb(panelp->pagenr, brdp->ioctrl);
3584
Jiri Slabyc62429d2006-12-08 02:39:14 -08003585 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 ioaddr = panelp->iobase + (i * 4);
3587 outb(SCCR, (ioaddr + XP_ADDR));
3588 outb(CR_RESETALL, (ioaddr + XP_DATA));
3589 outb(TSTR, (ioaddr + XP_ADDR));
3590 if (inb(ioaddr + XP_DATA) != 0) {
3591 printk("STALLION: sc26198 not responding, "
3592 "brd=%d panel=%d chip=%d\n",
3593 panelp->brdnr, panelp->panelnr, i);
3594 continue;
3595 }
3596 chipmask |= (0x1 << i);
3597 outb(GCCR, (ioaddr + XP_ADDR));
3598 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3599 outb(WDTRCR, (ioaddr + XP_ADDR));
3600 outb(0xff, (ioaddr + XP_DATA));
3601 }
3602
3603 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003604 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605}
3606
3607/*****************************************************************************/
3608
3609/*
3610 * Initialize hardware specific port registers.
3611 */
3612
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003613static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614{
Jiri Slabya0564e12006-12-08 02:38:37 -08003615 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3616 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
Jiri Slaby615e4a72006-12-08 02:38:38 -08003618 if ((brdp == NULL) || (panelp == NULL) ||
3619 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 return;
3621
3622 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3623 portp->uartaddr = (portp->portnr & 0x07) << 4;
3624 portp->pagenr = panelp->pagenr;
3625 portp->hwid = 0x1;
3626
3627 BRDENABLE(portp->brdnr, portp->pagenr);
3628 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3629 BRDDISABLE(portp->brdnr);
3630}
3631
3632/*****************************************************************************/
3633
3634/*
3635 * Set up the sc26198 registers for a port based on the termios port
3636 * settings.
3637 */
3638
Alan Cox606d0992006-12-08 02:38:45 -08003639static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003641 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 unsigned long flags;
3643 unsigned int baudrate;
3644 unsigned char mr0, mr1, mr2, clk;
3645 unsigned char imron, imroff, iopr, ipr;
3646
3647 mr0 = 0;
3648 mr1 = 0;
3649 mr2 = 0;
3650 clk = 0;
3651 iopr = 0;
3652 imron = 0;
3653 imroff = 0;
3654
3655 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003656 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 return;
3658
3659/*
3660 * Set up the RX char ignore mask with those RX error types we
3661 * can ignore.
3662 */
3663 portp->rxignoremsk = 0;
3664 if (tiosp->c_iflag & IGNPAR)
3665 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3666 SR_RXOVERRUN);
3667 if (tiosp->c_iflag & IGNBRK)
3668 portp->rxignoremsk |= SR_RXBREAK;
3669
3670 portp->rxmarkmsk = SR_RXOVERRUN;
3671 if (tiosp->c_iflag & (INPCK | PARMRK))
3672 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3673 if (tiosp->c_iflag & BRKINT)
3674 portp->rxmarkmsk |= SR_RXBREAK;
3675
3676/*
3677 * Go through the char size, parity and stop bits and set all the
3678 * option register appropriately.
3679 */
3680 switch (tiosp->c_cflag & CSIZE) {
3681 case CS5:
3682 mr1 |= MR1_CS5;
3683 break;
3684 case CS6:
3685 mr1 |= MR1_CS6;
3686 break;
3687 case CS7:
3688 mr1 |= MR1_CS7;
3689 break;
3690 default:
3691 mr1 |= MR1_CS8;
3692 break;
3693 }
3694
3695 if (tiosp->c_cflag & CSTOPB)
3696 mr2 |= MR2_STOP2;
3697 else
3698 mr2 |= MR2_STOP1;
3699
3700 if (tiosp->c_cflag & PARENB) {
3701 if (tiosp->c_cflag & PARODD)
3702 mr1 |= (MR1_PARENB | MR1_PARODD);
3703 else
3704 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003705 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
3708 mr1 |= MR1_ERRBLOCK;
3709
3710/*
3711 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3712 * space for hardware flow control and the like. This should be set to
3713 * VMIN.
3714 */
3715 mr2 |= MR2_RXFIFOHALF;
3716
3717/*
3718 * Calculate the baud rate timers. For now we will just assume that
3719 * the input and output baud are the same. The sc26198 has a fixed
3720 * baud rate table, so only discrete baud rates possible.
3721 */
3722 baudrate = tiosp->c_cflag & CBAUD;
3723 if (baudrate & CBAUDEX) {
3724 baudrate &= ~CBAUDEX;
3725 if ((baudrate < 1) || (baudrate > 4))
3726 tiosp->c_cflag &= ~CBAUDEX;
3727 else
3728 baudrate += 15;
3729 }
3730 baudrate = stl_baudrates[baudrate];
3731 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003732 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003734 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003736 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003738 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003740 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 baudrate = (portp->baud_base / portp->custom_divisor);
3742 }
3743 if (baudrate > STL_SC26198MAXBAUD)
3744 baudrate = STL_SC26198MAXBAUD;
3745
Jiri Slabyc62429d2006-12-08 02:39:14 -08003746 if (baudrate > 0)
3747 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748 if (baudrate <= sc26198_baudtable[clk])
3749 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750
3751/*
3752 * Check what form of modem signaling is required and set it up.
3753 */
3754 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003755 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 } else {
3757 iopr |= IOPR_DCDCOS;
3758 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003759 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 }
3761
3762/*
3763 * Setup sc26198 enhanced modes if we can. In particular we want to
3764 * handle as much of the flow control as possible automatically. As
3765 * well as saving a few CPU cycles it will also greatly improve flow
3766 * control reliability.
3767 */
3768 if (tiosp->c_iflag & IXON) {
3769 mr0 |= MR0_SWFTX | MR0_SWFT;
3770 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003771 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003773
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 if (tiosp->c_iflag & IXOFF)
3775 mr0 |= MR0_SWFRX;
3776
3777 if (tiosp->c_cflag & CRTSCTS) {
3778 mr2 |= MR2_AUTOCTS;
3779 mr1 |= MR1_AUTORTS;
3780 }
3781
3782/*
3783 * All sc26198 register values calculated so go through and set
3784 * them all up.
3785 */
3786
Jiri Slabya0564e12006-12-08 02:38:37 -08003787 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003789 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3790 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3791 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3793 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
Alan Coxb65b5b52006-06-27 02:54:05 -07003795 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 BRDENABLE(portp->brdnr, portp->pagenr);
3797 stl_sc26198setreg(portp, IMR, 0);
3798 stl_sc26198updatereg(portp, MR0, mr0);
3799 stl_sc26198updatereg(portp, MR1, mr1);
3800 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3801 stl_sc26198updatereg(portp, MR2, mr2);
3802 stl_sc26198updatereg(portp, IOPIOR,
3803 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3804
3805 if (baudrate > 0) {
3806 stl_sc26198setreg(portp, TXCSR, clk);
3807 stl_sc26198setreg(portp, RXCSR, clk);
3808 }
3809
3810 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3811 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3812
3813 ipr = stl_sc26198getreg(portp, IPR);
3814 if (ipr & IPR_DCD)
3815 portp->sigs &= ~TIOCM_CD;
3816 else
3817 portp->sigs |= TIOCM_CD;
3818
3819 portp->imr = (portp->imr & ~imroff) | imron;
3820 stl_sc26198setreg(portp, IMR, portp->imr);
3821 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003822 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823}
3824
3825/*****************************************************************************/
3826
3827/*
3828 * Set the state of the DTR and RTS signals.
3829 */
3830
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003831static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832{
3833 unsigned char iopioron, iopioroff;
3834 unsigned long flags;
3835
Jiri Slabya0564e12006-12-08 02:38:37 -08003836 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3837 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
3839 iopioron = 0;
3840 iopioroff = 0;
3841 if (dtr == 0)
3842 iopioroff |= IPR_DTR;
3843 else if (dtr > 0)
3844 iopioron |= IPR_DTR;
3845 if (rts == 0)
3846 iopioroff |= IPR_RTS;
3847 else if (rts > 0)
3848 iopioron |= IPR_RTS;
3849
Alan Coxb65b5b52006-06-27 02:54:05 -07003850 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 BRDENABLE(portp->brdnr, portp->pagenr);
3852 stl_sc26198setreg(portp, IOPIOR,
3853 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3854 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003855 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856}
3857
3858/*****************************************************************************/
3859
3860/*
3861 * Return the state of the signals.
3862 */
3863
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003864static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865{
3866 unsigned char ipr;
3867 unsigned long flags;
3868 int sigs;
3869
Jiri Slabya0564e12006-12-08 02:38:37 -08003870 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Alan Coxb65b5b52006-06-27 02:54:05 -07003872 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 BRDENABLE(portp->brdnr, portp->pagenr);
3874 ipr = stl_sc26198getreg(portp, IPR);
3875 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003876 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
3878 sigs = 0;
3879 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3880 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3881 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3882 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3883 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003884 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885}
3886
3887/*****************************************************************************/
3888
3889/*
3890 * Enable/Disable the Transmitter and/or Receiver.
3891 */
3892
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003893static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894{
3895 unsigned char ccr;
3896 unsigned long flags;
3897
Jiri Slabya0564e12006-12-08 02:38:37 -08003898 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
3900 ccr = portp->crenable;
3901 if (tx == 0)
3902 ccr &= ~CR_TXENABLE;
3903 else if (tx > 0)
3904 ccr |= CR_TXENABLE;
3905 if (rx == 0)
3906 ccr &= ~CR_RXENABLE;
3907 else if (rx > 0)
3908 ccr |= CR_RXENABLE;
3909
Alan Coxb65b5b52006-06-27 02:54:05 -07003910 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 BRDENABLE(portp->brdnr, portp->pagenr);
3912 stl_sc26198setreg(portp, SCCR, ccr);
3913 BRDDISABLE(portp->brdnr);
3914 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003915 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916}
3917
3918/*****************************************************************************/
3919
3920/*
3921 * Start/stop the Transmitter and/or Receiver.
3922 */
3923
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003924static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925{
3926 unsigned char imr;
3927 unsigned long flags;
3928
Jiri Slabya0564e12006-12-08 02:38:37 -08003929 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
3931 imr = portp->imr;
3932 if (tx == 0)
3933 imr &= ~IR_TXRDY;
3934 else if (tx == 1)
3935 imr |= IR_TXRDY;
3936 if (rx == 0)
3937 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3938 else if (rx > 0)
3939 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3940
Alan Coxb65b5b52006-06-27 02:54:05 -07003941 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 BRDENABLE(portp->brdnr, portp->pagenr);
3943 stl_sc26198setreg(portp, IMR, imr);
3944 BRDDISABLE(portp->brdnr);
3945 portp->imr = imr;
3946 if (tx > 0)
3947 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003948 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949}
3950
3951/*****************************************************************************/
3952
3953/*
3954 * Disable all interrupts from this port.
3955 */
3956
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003957static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958{
3959 unsigned long flags;
3960
Jiri Slabya0564e12006-12-08 02:38:37 -08003961 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Alan Coxb65b5b52006-06-27 02:54:05 -07003963 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 BRDENABLE(portp->brdnr, portp->pagenr);
3965 portp->imr = 0;
3966 stl_sc26198setreg(portp, IMR, 0);
3967 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003968 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969}
3970
3971/*****************************************************************************/
3972
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003973static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974{
3975 unsigned long flags;
3976
Jiri Slabya0564e12006-12-08 02:38:37 -08003977 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978
Alan Coxb65b5b52006-06-27 02:54:05 -07003979 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 BRDENABLE(portp->brdnr, portp->pagenr);
3981 if (len == 1) {
3982 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
3983 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003984 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003986
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003988 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989}
3990
3991/*****************************************************************************/
3992
3993/*
3994 * Take flow control actions...
3995 */
3996
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003997static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998{
3999 struct tty_struct *tty;
4000 unsigned long flags;
4001 unsigned char mr0;
4002
Jiri Slabya0564e12006-12-08 02:38:37 -08004003 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004
Jiri Slaby615e4a72006-12-08 02:38:38 -08004005 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004007 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004008 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 return;
4010
Alan Coxb65b5b52006-06-27 02:54:05 -07004011 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 BRDENABLE(portp->brdnr, portp->pagenr);
4013
4014 if (state) {
4015 if (tty->termios->c_iflag & IXOFF) {
4016 mr0 = stl_sc26198getreg(portp, MR0);
4017 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4018 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4019 mr0 |= MR0_SWFRX;
4020 portp->stats.rxxon++;
4021 stl_sc26198wait(portp);
4022 stl_sc26198setreg(portp, MR0, mr0);
4023 }
4024/*
4025 * Question: should we return RTS to what it was before? It may
4026 * have been set by an ioctl... Suppose not, since if you have
4027 * hardware flow control set then it is pretty silly to go and
4028 * set the RTS line by hand.
4029 */
4030 if (tty->termios->c_cflag & CRTSCTS) {
4031 stl_sc26198setreg(portp, MR1,
4032 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4033 stl_sc26198setreg(portp, IOPIOR,
4034 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4035 portp->stats.rxrtson++;
4036 }
4037 } else {
4038 if (tty->termios->c_iflag & IXOFF) {
4039 mr0 = stl_sc26198getreg(portp, MR0);
4040 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4041 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4042 mr0 &= ~MR0_SWFRX;
4043 portp->stats.rxxoff++;
4044 stl_sc26198wait(portp);
4045 stl_sc26198setreg(portp, MR0, mr0);
4046 }
4047 if (tty->termios->c_cflag & CRTSCTS) {
4048 stl_sc26198setreg(portp, MR1,
4049 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4050 stl_sc26198setreg(portp, IOPIOR,
4051 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4052 portp->stats.rxrtsoff++;
4053 }
4054 }
4055
4056 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004057 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004058 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059}
4060
4061/*****************************************************************************/
4062
4063/*
4064 * Send a flow control character.
4065 */
4066
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004067static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068{
4069 struct tty_struct *tty;
4070 unsigned long flags;
4071 unsigned char mr0;
4072
Jiri Slabya0564e12006-12-08 02:38:37 -08004073 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Jiri Slaby615e4a72006-12-08 02:38:38 -08004075 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004077 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004078 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 return;
4080
Alan Coxb65b5b52006-06-27 02:54:05 -07004081 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 BRDENABLE(portp->brdnr, portp->pagenr);
4083 if (state) {
4084 mr0 = stl_sc26198getreg(portp, MR0);
4085 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4086 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4087 mr0 |= MR0_SWFRX;
4088 portp->stats.rxxon++;
4089 stl_sc26198wait(portp);
4090 stl_sc26198setreg(portp, MR0, mr0);
4091 } else {
4092 mr0 = stl_sc26198getreg(portp, MR0);
4093 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4094 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4095 mr0 &= ~MR0_SWFRX;
4096 portp->stats.rxxoff++;
4097 stl_sc26198wait(portp);
4098 stl_sc26198setreg(portp, MR0, mr0);
4099 }
4100 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004101 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004102 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103}
4104
4105/*****************************************************************************/
4106
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004107static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108{
4109 unsigned long flags;
4110
Jiri Slabya0564e12006-12-08 02:38:37 -08004111 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Jiri Slaby615e4a72006-12-08 02:38:38 -08004113 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 return;
4115
Alan Coxb65b5b52006-06-27 02:54:05 -07004116 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 BRDENABLE(portp->brdnr, portp->pagenr);
4118 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4119 stl_sc26198setreg(portp, SCCR, portp->crenable);
4120 BRDDISABLE(portp->brdnr);
4121 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004122 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123}
4124
4125/*****************************************************************************/
4126
4127/*
4128 * Return the current state of data flow on this port. This is only
4129 * really interresting when determining if data has fully completed
4130 * transmission or not... The sc26198 interrupt scheme cannot
4131 * determine when all data has actually drained, so we need to
4132 * check the port statusy register to be sure.
4133 */
4134
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004135static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136{
4137 unsigned long flags;
4138 unsigned char sr;
4139
Jiri Slabya0564e12006-12-08 02:38:37 -08004140 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141
Jiri Slaby615e4a72006-12-08 02:38:38 -08004142 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004143 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004145 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Alan Coxb65b5b52006-06-27 02:54:05 -07004147 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 BRDENABLE(portp->brdnr, portp->pagenr);
4149 sr = stl_sc26198getreg(portp, SR);
4150 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004151 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Jesper Juhl014c2542006-01-15 02:37:08 +01004153 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154}
4155
4156/*****************************************************************************/
4157
4158/*
4159 * Delay for a small amount of time, to give the sc26198 a chance
4160 * to process a command...
4161 */
4162
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004163static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164{
4165 int i;
4166
Jiri Slabya0564e12006-12-08 02:38:37 -08004167 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
Jiri Slaby615e4a72006-12-08 02:38:38 -08004169 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 return;
4171
Jiri Slabyc62429d2006-12-08 02:39:14 -08004172 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 stl_sc26198getglobreg(portp, TSTR);
4174}
4175
4176/*****************************************************************************/
4177
4178/*
4179 * If we are TX flow controlled and in IXANY mode then we may
4180 * need to unflow control here. We gotta do this because of the
4181 * automatic flow control modes of the sc26198.
4182 */
4183
Jiri Slaby60be4812006-12-08 02:38:40 -08004184static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185{
4186 unsigned char mr0;
4187
4188 mr0 = stl_sc26198getreg(portp, MR0);
4189 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4190 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4191 stl_sc26198wait(portp);
4192 stl_sc26198setreg(portp, MR0, mr0);
4193 clear_bit(ASYI_TXFLOWED, &portp->istate);
4194}
4195
4196/*****************************************************************************/
4197
4198/*
4199 * Interrupt service routine for sc26198 panels.
4200 */
4201
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004202static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004204 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 unsigned int iack;
4206
Alan Coxb65b5b52006-06-27 02:54:05 -07004207 spin_lock(&brd_lock);
4208
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209/*
4210 * Work around bug in sc26198 chip... Cannot have A6 address
4211 * line of UART high, else iack will be returned as 0.
4212 */
4213 outb(0, (iobase + 1));
4214
4215 iack = inb(iobase + XP_IACK);
4216 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4217
4218 if (iack & IVR_RXDATA)
4219 stl_sc26198rxisr(portp, iack);
4220 else if (iack & IVR_TXDATA)
4221 stl_sc26198txisr(portp);
4222 else
4223 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004224
4225 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226}
4227
4228/*****************************************************************************/
4229
4230/*
4231 * Transmit interrupt handler. This has gotta be fast! Handling TX
4232 * chars is pretty simple, stuff as many as possible from the TX buffer
4233 * into the sc26198 FIFO.
4234 * In practice it is possible that interrupts are enabled but that the
4235 * port has been hung up. Need to handle not having any TX buffer here,
4236 * this is done by using the side effect that head and tail will also
4237 * be NULL if the buffer has been freed.
4238 */
4239
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004240static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241{
Alan Coxd18a7502008-10-13 10:40:07 +01004242 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 unsigned int ioaddr;
4244 unsigned char mr0;
4245 int len, stlen;
4246 char *head, *tail;
4247
Jiri Slabya0564e12006-12-08 02:38:37 -08004248 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
4250 ioaddr = portp->ioaddr;
4251 head = portp->tx.head;
4252 tail = portp->tx.tail;
4253 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4254 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4255 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4256 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004257 tty = tty_port_tty_get(&portp->port);
4258 if (tty) {
4259 tty_wakeup(tty);
4260 tty_kref_put(tty);
4261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 }
4263
4264 if (len == 0) {
4265 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4266 mr0 = inb(ioaddr + XP_DATA);
4267 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4268 portp->imr &= ~IR_TXRDY;
4269 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4270 outb(portp->imr, (ioaddr + XP_DATA));
4271 clear_bit(ASYI_TXBUSY, &portp->istate);
4272 } else {
4273 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4274 outb(mr0, (ioaddr + XP_DATA));
4275 }
4276 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004277 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004279 stlen = min_t(unsigned int, len,
4280 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 outb(GTXFIFO, (ioaddr + XP_ADDR));
4282 outsb((ioaddr + XP_DATA), tail, stlen);
4283 len -= stlen;
4284 tail += stlen;
4285 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4286 tail = portp->tx.buf;
4287 if (len > 0) {
4288 outsb((ioaddr + XP_DATA), tail, len);
4289 tail += len;
4290 }
4291 portp->tx.tail = tail;
4292 }
4293}
4294
4295/*****************************************************************************/
4296
4297/*
4298 * Receive character interrupt handler. Determine if we have good chars
4299 * or bad chars and then process appropriately. Good chars are easy
4300 * just shove the lot into the RX buffer and set all status byte to 0.
4301 * If a bad RX char then process as required. This routine needs to be
4302 * fast! In practice it is possible that we get an interrupt on a port
4303 * that is closed. This can happen on hangups - since they completely
4304 * shutdown a port not in user context. Need to handle this case.
4305 */
4306
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004307static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308{
4309 struct tty_struct *tty;
4310 unsigned int len, buflen, ioaddr;
4311
Jiri Slabya0564e12006-12-08 02:38:37 -08004312 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313
Alan Coxd18a7502008-10-13 10:40:07 +01004314 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315 ioaddr = portp->ioaddr;
4316 outb(GIBCR, (ioaddr + XP_ADDR));
4317 len = inb(ioaddr + XP_DATA) + 1;
4318
4319 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004320 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004321 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322 outb(GRXFIFO, (ioaddr + XP_ADDR));
4323 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4324 portp->stats.rxlost += len;
4325 portp->stats.rxtotal += len;
4326 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004327 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004329 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004331 tty_prepare_flip_string(tty, &ptr, len);
4332 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 tty_schedule_flip(tty);
4334 portp->stats.rxtotal += len;
4335 }
4336 }
4337 } else {
4338 stl_sc26198rxbadchars(portp);
4339 }
4340
4341/*
4342 * If we are TX flow controlled and in IXANY mode then we may need
4343 * to unflow control here. We gotta do this because of the automatic
4344 * flow control modes of the sc26198.
4345 */
4346 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004347 if ((tty != NULL) &&
4348 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 (tty->termios->c_iflag & IXANY)) {
4350 stl_sc26198txunflow(portp, tty);
4351 }
4352 }
Alan Coxd18a7502008-10-13 10:40:07 +01004353 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354}
4355
4356/*****************************************************************************/
4357
4358/*
4359 * Process an RX bad character.
4360 */
4361
Jiri Slaby60be4812006-12-08 02:38:40 -08004362static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363{
4364 struct tty_struct *tty;
4365 unsigned int ioaddr;
4366
Alan Coxd18a7502008-10-13 10:40:07 +01004367 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368 ioaddr = portp->ioaddr;
4369
4370 if (status & SR_RXPARITY)
4371 portp->stats.rxparity++;
4372 if (status & SR_RXFRAMING)
4373 portp->stats.rxframing++;
4374 if (status & SR_RXOVERRUN)
4375 portp->stats.rxoverrun++;
4376 if (status & SR_RXBREAK)
4377 portp->stats.rxbreaks++;
4378
Jiri Slaby615e4a72006-12-08 02:38:38 -08004379 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 ((portp->rxignoremsk & status) == 0)) {
4381 if (portp->rxmarkmsk & status) {
4382 if (status & SR_RXBREAK) {
4383 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004384 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 do_SAK(tty);
4386 BRDENABLE(portp->brdnr, portp->pagenr);
4387 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004388 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004390 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004392 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004394 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004396 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Alan Cox33f0f882006-01-09 20:54:13 -08004399 tty_insert_flip_char(tty, ch, status);
4400 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
4402 if (status == 0)
4403 portp->stats.rxtotal++;
4404 }
Alan Coxd18a7502008-10-13 10:40:07 +01004405 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406}
4407
4408/*****************************************************************************/
4409
4410/*
4411 * Process all characters in the RX FIFO of the UART. Check all char
4412 * status bytes as well, and process as required. We need to check
4413 * all bytes in the FIFO, in case some more enter the FIFO while we
4414 * are here. To get the exact character error type we need to switch
4415 * into CHAR error mode (that is why we need to make sure we empty
4416 * the FIFO).
4417 */
4418
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004419static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420{
4421 unsigned char status, mr1;
4422 char ch;
4423
4424/*
4425 * To get the precise error type for each character we must switch
4426 * back into CHAR error mode.
4427 */
4428 mr1 = stl_sc26198getreg(portp, MR1);
4429 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4430
4431 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4432 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4433 ch = stl_sc26198getreg(portp, RXFIFO);
4434 stl_sc26198rxbadch(portp, status, ch);
4435 }
4436
4437/*
4438 * To get correct interrupt class we must switch back into BLOCK
4439 * error mode.
4440 */
4441 stl_sc26198setreg(portp, MR1, mr1);
4442}
4443
4444/*****************************************************************************/
4445
4446/*
4447 * Other interrupt handler. This includes modem signals, flow
4448 * control actions, etc. Most stuff is left to off-level interrupt
4449 * processing time.
4450 */
4451
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004452static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453{
4454 unsigned char cir, ipr, xisr;
4455
Jiri Slabya0564e12006-12-08 02:38:37 -08004456 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457
4458 cir = stl_sc26198getglobreg(portp, CIR);
4459
4460 switch (cir & CIR_SUBTYPEMASK) {
4461 case CIR_SUBCOS:
4462 ipr = stl_sc26198getreg(portp, IPR);
4463 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004464 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465 portp->stats.modem++;
4466 }
4467 break;
4468 case CIR_SUBXONXOFF:
4469 xisr = stl_sc26198getreg(portp, XISR);
4470 if (xisr & XISR_RXXONGOT) {
4471 set_bit(ASYI_TXFLOWED, &portp->istate);
4472 portp->stats.txxoff++;
4473 }
4474 if (xisr & XISR_RXXOFFGOT) {
4475 clear_bit(ASYI_TXFLOWED, &portp->istate);
4476 portp->stats.txxon++;
4477 }
4478 break;
4479 case CIR_SUBBREAK:
4480 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4481 stl_sc26198rxbadchars(portp);
4482 break;
4483 default:
4484 break;
4485 }
4486}
4487
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004488static void stl_free_isabrds(void)
4489{
4490 struct stlbrd *brdp;
4491 unsigned int i;
4492
4493 for (i = 0; i < stl_nrbrds; i++) {
4494 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4495 continue;
4496
4497 free_irq(brdp->irq, brdp);
4498
4499 stl_cleanup_panels(brdp);
4500
4501 release_region(brdp->ioaddr1, brdp->iosize1);
4502 if (brdp->iosize2 > 0)
4503 release_region(brdp->ioaddr2, brdp->iosize2);
4504
4505 kfree(brdp);
4506 stl_brds[i] = NULL;
4507 }
4508}
4509
Jiri Slaby23b85a12006-12-08 02:38:40 -08004510/*
4511 * Loadable module initialization stuff.
4512 */
4513static int __init stallion_module_init(void)
4514{
Jiri Slaby843b5682006-12-08 02:39:12 -08004515 struct stlbrd *brdp;
4516 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004517 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004518 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004519
4520 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4521
4522 spin_lock_init(&stallion_lock);
4523 spin_lock_init(&brd_lock);
4524
Jiri Slabye4151092007-06-08 13:46:52 -07004525 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4526 if (!stl_serial) {
4527 retval = -ENOMEM;
4528 goto err;
4529 }
4530
4531 stl_serial->owner = THIS_MODULE;
4532 stl_serial->driver_name = stl_drvname;
4533 stl_serial->name = "ttyE";
4534 stl_serial->major = STL_SERIALMAJOR;
4535 stl_serial->minor_start = 0;
4536 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4537 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4538 stl_serial->init_termios = stl_deftermios;
4539 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4540 tty_set_operations(stl_serial, &stl_ops);
4541
4542 retval = tty_register_driver(stl_serial);
4543 if (retval) {
4544 printk("STALLION: failed to register serial driver\n");
4545 goto err_frtty;
4546 }
4547
Jiri Slaby843b5682006-12-08 02:39:12 -08004548/*
4549 * Find any dynamically supported boards. That is via module load
4550 * line options.
4551 */
4552 for (i = stl_nrbrds; i < stl_nargs; i++) {
4553 memset(&conf, 0, sizeof(conf));
4554 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4555 continue;
4556 if ((brdp = stl_allocbrd()) == NULL)
4557 continue;
4558 brdp->brdnr = i;
4559 brdp->brdtype = conf.brdtype;
4560 brdp->ioaddr1 = conf.ioaddr1;
4561 brdp->ioaddr2 = conf.ioaddr2;
4562 brdp->irq = conf.irq;
4563 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004564 stl_brds[brdp->brdnr] = brdp;
4565 if (stl_brdinit(brdp)) {
4566 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004567 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004568 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004569 for (j = 0; j < brdp->nrports; j++)
4570 tty_register_device(stl_serial,
4571 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004572 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004573 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004574 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004575
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004576 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004577 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004578 if (retval && stl_nrbrds == 0) {
4579 printk(KERN_ERR "STALLION: can't register pci driver\n");
4580 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004581 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004582
4583/*
4584 * Set up a character driver for per board stuff. This is mainly used
4585 * to do stats ioctls on the ports.
4586 */
4587 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4588 printk("STALLION: failed to register serial board device\n");
4589
4590 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004591 if (IS_ERR(stallion_class))
4592 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004593 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004594 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4595 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004596
Jiri Slaby23b85a12006-12-08 02:38:40 -08004597 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004598err_unrtty:
4599 tty_unregister_driver(stl_serial);
4600err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004601 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004602err:
4603 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004604}
4605
4606static void __exit stallion_module_exit(void)
4607{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004608 struct stlbrd *brdp;
4609 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004610
4611 pr_debug("cleanup_module()\n");
4612
4613 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4614 stl_drvversion);
4615
4616/*
4617 * Free up all allocated resources used by the ports. This includes
4618 * memory and interrupts. As part of this process we will also do
4619 * a hangup on every open port - to try to flush out any processes
4620 * hanging onto ports.
4621 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004622 for (i = 0; i < stl_nrbrds; i++) {
4623 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4624 continue;
4625 for (j = 0; j < brdp->nrports; j++)
4626 tty_unregister_device(stl_serial,
4627 brdp->brdnr * STL_MAXPORTS + j);
4628 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004629
Jiri Slaby23b85a12006-12-08 02:38:40 -08004630 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004631 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004632 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004633 class_destroy(stallion_class);
4634
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004635 pci_unregister_driver(&stl_pcidriver);
4636
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004637 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004638
4639 tty_unregister_driver(stl_serial);
4640 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004641}
4642
4643module_init(stallion_module_init);
4644module_exit(stallion_module_exit);
4645
4646MODULE_AUTHOR("Greg Ungerer");
4647MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4648MODULE_LICENSE("GPL");