blob: 0e511d61f544eac34417456e509d86bedfd13624 [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;
Alan Cox4350f3f2009-01-02 13:46:24 +0000727 struct tty_port *port;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800728 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000729 int portnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
Jiri Slabya0564e12006-12-08 02:38:37 -0800731 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 minordev = tty->index;
734 brdnr = MINOR2BRD(minordev);
735 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100736 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800738 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100739 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800742 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800743 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 break;
745 if (minordev < brdp->panels[panelnr]->nrports) {
746 portnr = minordev;
747 break;
748 }
749 minordev -= brdp->panels[panelnr]->nrports;
750 }
751 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100752 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
754 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800755 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100756 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000757 port = &portp->port;
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;
844 BUG_ON(portp == NULL);
845 tty_port_close(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846}
847
848/*****************************************************************************/
849
850/*
851 * Write routine. Take data and stuff it in to the TX ring queue.
852 * If transmit interrupts are not running then start them.
853 */
854
855static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
856{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800857 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 unsigned int len, stlen;
859 unsigned char *chbuf;
860 char *head, *tail;
861
Jiri Slabya0564e12006-12-08 02:38:37 -0800862 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800865 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100866 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800867 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100868 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
870/*
871 * If copying direct from user space we must cater for page faults,
872 * causing us to "sleep" here for a while. To handle this copy in all
873 * the data we need now, into a local buffer. Then when we got it all
874 * copy it into the TX buffer.
875 */
876 chbuf = (unsigned char *) buf;
877
878 head = portp->tx.head;
879 tail = portp->tx.tail;
880 if (head >= tail) {
881 len = STL_TXBUFSIZE - (head - tail) - 1;
882 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
883 } else {
884 len = tail - head - 1;
885 stlen = len;
886 }
887
Jiri Slaby843b5682006-12-08 02:39:12 -0800888 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 count = 0;
890 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800891 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 memcpy(head, chbuf, stlen);
893 len -= stlen;
894 chbuf += stlen;
895 count += stlen;
896 head += stlen;
897 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
898 head = portp->tx.buf;
899 stlen = tail - head;
900 }
901 }
902 portp->tx.head = head;
903
904 clear_bit(ASYI_TXLOW, &portp->istate);
905 stl_startrxtx(portp, -1, 1);
906
Jesper Juhl014c2542006-01-15 02:37:08 +0100907 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908}
909
910/*****************************************************************************/
911
David Howells4a561222008-07-22 11:18:43 +0100912static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800914 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 unsigned int len;
916 char *head, *tail;
917
Jiri Slabya0564e12006-12-08 02:38:37 -0800918 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800921 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100922 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800923 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100924 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
926 head = portp->tx.head;
927 tail = portp->tx.tail;
928
929 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
930 len--;
931
932 if (len > 0) {
933 *head++ = ch;
934 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
935 head = portp->tx.buf;
936 }
937 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100938 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939}
940
941/*****************************************************************************/
942
943/*
944 * If there are any characters in the buffer then make sure that TX
945 * interrupts are on and get'em out. Normally used after the putchar
946 * routine has been called.
947 */
948
949static void stl_flushchars(struct tty_struct *tty)
950{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800951 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
Jiri Slabya0564e12006-12-08 02:38:37 -0800953 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800956 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800958 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 return;
960
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 stl_startrxtx(portp, -1, 1);
962}
963
964/*****************************************************************************/
965
966static int stl_writeroom(struct tty_struct *tty)
967{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800968 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 char *head, *tail;
970
Jiri Slabya0564e12006-12-08 02:38:37 -0800971 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800974 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100975 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800976 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100977 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
979 head = portp->tx.head;
980 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800981 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982}
983
984/*****************************************************************************/
985
986/*
987 * Return number of chars in the TX buffer. Normally we would just
988 * calculate the number of chars in the buffer and return that, but if
989 * the buffer is empty and TX interrupts are still on then we return
990 * that the buffer still has 1 char in it. This way whoever called us
991 * will not think that ALL chars have drained - since the UART still
992 * must have some chars in it (we are busy after all).
993 */
994
995static int stl_charsinbuffer(struct tty_struct *tty)
996{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800997 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 unsigned int size;
999 char *head, *tail;
1000
Jiri Slabya0564e12006-12-08 02:38:37 -08001001 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001004 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001005 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001006 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001007 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
1009 head = portp->tx.head;
1010 tail = portp->tx.tail;
1011 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1012 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1013 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001014 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015}
1016
1017/*****************************************************************************/
1018
1019/*
1020 * Generate the serial struct info.
1021 */
1022
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001023static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024{
1025 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001026 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Jiri Slabya0564e12006-12-08 02:38:37 -08001028 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 memset(&sio, 0, sizeof(struct serial_struct));
1031 sio.line = portp->portnr;
1032 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001033 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 sio.baud_base = portp->baud_base;
1035 sio.close_delay = portp->close_delay;
1036 sio.closing_wait = portp->closing_wait;
1037 sio.custom_divisor = portp->custom_divisor;
1038 sio.hub6 = 0;
1039 if (portp->uartp == &stl_cd1400uart) {
1040 sio.type = PORT_CIRRUS;
1041 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1042 } else {
1043 sio.type = PORT_UNKNOWN;
1044 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1045 }
1046
1047 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001048 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 sio.irq = brdp->irq;
1050
1051 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1052}
1053
1054/*****************************************************************************/
1055
1056/*
1057 * Set port according to the serial struct info.
1058 * At this point we do not do any auto-configure stuff, so we will
1059 * just quietly ignore any requests to change irq, etc.
1060 */
1061
Alan Coxd18a7502008-10-13 10:40:07 +01001062static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
Alan Coxd18a7502008-10-13 10:40:07 +01001064 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 struct serial_struct sio;
1066
Jiri Slabya0564e12006-12-08 02:38:37 -08001067 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1070 return -EFAULT;
1071 if (!capable(CAP_SYS_ADMIN)) {
1072 if ((sio.baud_base != portp->baud_base) ||
1073 (sio.close_delay != portp->close_delay) ||
1074 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001075 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001076 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 }
1078
Alan Coxf8ae4762008-07-16 21:56:37 +01001079 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 (sio.flags & ASYNC_USR_MASK);
1081 portp->baud_base = sio.baud_base;
1082 portp->close_delay = sio.close_delay;
1083 portp->closing_wait = sio.closing_wait;
1084 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001085 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001086 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087}
1088
1089/*****************************************************************************/
1090
1091static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1092{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001093 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001096 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001097 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001099 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 return stl_getsignals(portp);
1102}
1103
1104static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1105 unsigned int set, unsigned int clear)
1106{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001107 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 int rts = -1, dtr = -1;
1109
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001111 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001112 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001114 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116 if (set & TIOCM_RTS)
1117 rts = 1;
1118 if (set & TIOCM_DTR)
1119 dtr = 1;
1120 if (clear & TIOCM_RTS)
1121 rts = 0;
1122 if (clear & TIOCM_DTR)
1123 dtr = 0;
1124
1125 stl_setsignals(portp, dtr, rts);
1126 return 0;
1127}
1128
1129static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1130{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001131 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 int rc;
1133 void __user *argp = (void __user *)arg;
1134
Jiri Slabya0564e12006-12-08 02:38:37 -08001135 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1136 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001139 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001140 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
1142 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001143 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001145 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 rc = 0;
1148
Alan Coxf433c652008-04-30 00:53:23 -07001149 lock_kernel();
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 case TIOCGSERIAL:
1153 rc = stl_getserial(portp, argp);
1154 break;
1155 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001156 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 break;
1158 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001159 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 break;
1161 case COM_CLRPORTSTATS:
1162 rc = stl_clrportstats(portp, argp);
1163 break;
1164 case TIOCSERCONFIG:
1165 case TIOCSERGWILD:
1166 case TIOCSERSWILD:
1167 case TIOCSERGETLSR:
1168 case TIOCSERGSTRUCT:
1169 case TIOCSERGETMULTI:
1170 case TIOCSERSETMULTI:
1171 default:
1172 rc = -ENOIOCTLCMD;
1173 break;
1174 }
Alan Coxf433c652008-04-30 00:53:23 -07001175 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001176 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177}
1178
1179/*****************************************************************************/
1180
Jiri Slaby96b066b2006-12-08 02:38:42 -08001181/*
1182 * Start the transmitter again. Just turn TX interrupts back on.
1183 */
1184
1185static void stl_start(struct tty_struct *tty)
1186{
1187 struct stlport *portp;
1188
1189 pr_debug("stl_start(tty=%p)\n", tty);
1190
Jiri Slaby96b066b2006-12-08 02:38:42 -08001191 portp = tty->driver_data;
1192 if (portp == NULL)
1193 return;
1194 stl_startrxtx(portp, -1, 1);
1195}
1196
1197/*****************************************************************************/
1198
Alan Cox606d0992006-12-08 02:38:45 -08001199static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001201 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001202 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Jiri Slabya0564e12006-12-08 02:38:37 -08001204 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001207 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 return;
1209
1210 tiosp = tty->termios;
1211 if ((tiosp->c_cflag == old->c_cflag) &&
1212 (tiosp->c_iflag == old->c_iflag))
1213 return;
1214
1215 stl_setport(portp, tiosp);
1216 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1217 -1);
1218 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1219 tty->hw_stopped = 0;
1220 stl_start(tty);
1221 }
1222 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001223 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224}
1225
1226/*****************************************************************************/
1227
1228/*
1229 * Attempt to flow control who ever is sending us data. Based on termios
1230 * settings use software or/and hardware flow control.
1231 */
1232
1233static void stl_throttle(struct tty_struct *tty)
1234{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001235 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Jiri Slabya0564e12006-12-08 02:38:37 -08001237 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001240 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 return;
1242 stl_flowctrl(portp, 0);
1243}
1244
1245/*****************************************************************************/
1246
1247/*
1248 * Unflow control the device sending us data...
1249 */
1250
1251static void stl_unthrottle(struct tty_struct *tty)
1252{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001253 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
Jiri Slabya0564e12006-12-08 02:38:37 -08001255 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001258 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 return;
1260 stl_flowctrl(portp, 1);
1261}
1262
1263/*****************************************************************************/
1264
1265/*
1266 * Stop the transmitter. Basically to do this we will just turn TX
1267 * interrupts off.
1268 */
1269
1270static void stl_stop(struct tty_struct *tty)
1271{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001272 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Jiri Slabya0564e12006-12-08 02:38:37 -08001274 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001277 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 return;
1279 stl_startrxtx(portp, -1, 0);
1280}
1281
1282/*****************************************************************************/
1283
1284/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 * Hangup this port. This is pretty much like closing the port, only
1286 * a little more brutal. No waiting for data to drain. Shutdown the
1287 * port and maybe drop signals.
1288 */
1289
1290static void stl_hangup(struct tty_struct *tty)
1291{
Alan Cox047e9652009-11-30 13:17:03 +00001292 struct stlport *portp = tty->driver_data;
Jiri Slabya0564e12006-12-08 02:38:37 -08001293 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
Jiri Slaby615e4a72006-12-08 02:38:38 -08001295 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 return;
Alan Cox047e9652009-11-30 13:17:03 +00001297 tty_port_hangup(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298}
1299
1300/*****************************************************************************/
1301
David Howells4a561222008-07-22 11:18:43 +01001302static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001304 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
Jiri Slabya0564e12006-12-08 02:38:37 -08001306 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001309 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001310 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001313 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314}
1315
1316/*****************************************************************************/
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318static void stl_sendxchar(struct tty_struct *tty, char ch)
1319{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001320 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Jiri Slabya0564e12006-12-08 02:38:37 -08001322 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001325 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 return;
1327
1328 if (ch == STOP_CHAR(tty))
1329 stl_sendflow(portp, 0);
1330 else if (ch == START_CHAR(tty))
1331 stl_sendflow(portp, 1);
1332 else
1333 stl_putchar(tty, ch);
1334}
1335
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001336static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001338 int sigs;
1339 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001341 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1343 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1344
1345 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001346 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001348 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001350 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001352 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
1354 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001355 sep = ' ';
1356 if (sigs & TIOCM_RTS) {
1357 seq_printf(m, "%c%s", sep, "RTS");
1358 sep = '|';
1359 }
1360 if (sigs & TIOCM_CTS) {
1361 seq_printf(m, "%c%s", sep, "CTS");
1362 sep = '|';
1363 }
1364 if (sigs & TIOCM_DTR) {
1365 seq_printf(m, "%c%s", sep, "DTR");
1366 sep = '|';
1367 }
1368 if (sigs & TIOCM_CD) {
1369 seq_printf(m, "%c%s", sep, "DCD");
1370 sep = '|';
1371 }
1372 if (sigs & TIOCM_DSR) {
1373 seq_printf(m, "%c%s", sep, "DSR");
1374 sep = '|';
1375 }
1376 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377}
1378
1379/*****************************************************************************/
1380
1381/*
1382 * Port info, read from the /proc file system.
1383 */
1384
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001385static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001387 struct stlbrd *brdp;
1388 struct stlpanel *panelp;
1389 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001390 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001391 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001395 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397/*
1398 * We scan through for each board, panel and port. The offset is
1399 * calculated on the fly, and irrelevant ports are skipped.
1400 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001401 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001403 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 continue;
1405 if (brdp->state == 0)
1406 continue;
1407
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001409 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001411 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 continue;
1413
Jiri Slabyc62429d2006-12-08 02:39:14 -08001414 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 totalport++) {
1416 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001417 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001419 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 }
1421 }
1422 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001423 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424}
1425
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001426static int stl_proc_open(struct inode *inode, struct file *file)
1427{
1428 return single_open(file, stl_proc_show, NULL);
1429}
1430
1431static const struct file_operations stl_proc_fops = {
1432 .owner = THIS_MODULE,
1433 .open = stl_proc_open,
1434 .read = seq_read,
1435 .llseek = seq_lseek,
1436 .release = single_release,
1437};
1438
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439/*****************************************************************************/
1440
1441/*
1442 * All board interrupts are vectored through here first. This code then
1443 * calls off to the approrpriate board interrupt handlers.
1444 */
1445
David Howells7d12e782006-10-05 14:55:46 +01001446static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001448 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Jeff Garzika6f97b22007-10-31 05:20:49 -04001450 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 return IRQ_RETVAL((* brdp->isr)(brdp));
1453}
1454
1455/*****************************************************************************/
1456
1457/*
1458 * Interrupt service routine for EasyIO board types.
1459 */
1460
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001461static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001463 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 unsigned int iobase;
1465 int handled = 0;
1466
Alan Coxb65b5b52006-06-27 02:54:05 -07001467 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 panelp = brdp->panels[0];
1469 iobase = panelp->iobase;
1470 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1471 handled = 1;
1472 (* panelp->isr)(panelp, iobase);
1473 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001474 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 return handled;
1476}
1477
1478/*****************************************************************************/
1479
1480/*
1481 * Interrupt service routine for ECH-AT board types.
1482 */
1483
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001484static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001486 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001487 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 int handled = 0;
1489
1490 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1491
1492 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1493 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001494 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 ioaddr = brdp->bnkstataddr[bnknr];
1496 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1497 panelp = brdp->bnk2panel[bnknr];
1498 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1499 }
1500 }
1501 }
1502
1503 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1504
1505 return handled;
1506}
1507
1508/*****************************************************************************/
1509
1510/*
1511 * Interrupt service routine for ECH-MCA board types.
1512 */
1513
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001514static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001516 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001517 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 int handled = 0;
1519
1520 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1521 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001522 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 ioaddr = brdp->bnkstataddr[bnknr];
1524 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1525 panelp = brdp->bnk2panel[bnknr];
1526 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1527 }
1528 }
1529 }
1530 return handled;
1531}
1532
1533/*****************************************************************************/
1534
1535/*
1536 * Interrupt service routine for ECH-PCI board types.
1537 */
1538
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001539static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001541 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001542 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 int handled = 0;
1544
1545 while (1) {
1546 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001547 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1549 ioaddr = brdp->bnkstataddr[bnknr];
1550 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1551 panelp = brdp->bnk2panel[bnknr];
1552 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1553 recheck++;
1554 handled = 1;
1555 }
1556 }
1557 if (! recheck)
1558 break;
1559 }
1560 return handled;
1561}
1562
1563/*****************************************************************************/
1564
1565/*
1566 * Interrupt service routine for ECH-8/64-PCI board types.
1567 */
1568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001569static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001571 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001572 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 int handled = 0;
1574
1575 while (inb(brdp->ioctrl) & 0x1) {
1576 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001577 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 ioaddr = brdp->bnkstataddr[bnknr];
1579 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1580 panelp = brdp->bnk2panel[bnknr];
1581 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1582 }
1583 }
1584 }
1585
1586 return handled;
1587}
1588
1589/*****************************************************************************/
1590
1591/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 * Initialize all the ports on a panel.
1593 */
1594
Jiri Slaby705c1862006-12-08 02:39:11 -08001595static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001597 struct stlport *portp;
1598 unsigned int i;
1599 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Jiri Slabya0564e12006-12-08 02:38:37 -08001601 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
1603 chipmask = stl_panelinit(brdp, panelp);
1604
1605/*
1606 * All UART's are initialized (if found!). Now go through and setup
1607 * each ports data structures.
1608 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001609 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001610 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001611 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001613 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 break;
1615 }
Alan Coxd18a7502008-10-13 10:40:07 +01001616 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001617 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 portp->magic = STL_PORTMAGIC;
1619 portp->portnr = i;
1620 portp->brdnr = panelp->brdnr;
1621 portp->panelnr = panelp->panelnr;
1622 portp->uartp = panelp->uartp;
1623 portp->clk = brdp->clk;
1624 portp->baud_base = STL_BAUDBASE;
1625 portp->close_delay = STL_CLOSEDELAY;
1626 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001627 init_waitqueue_head(&portp->port.open_wait);
1628 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 portp->stats.brd = portp->brdnr;
1630 portp->stats.panel = portp->panelnr;
1631 portp->stats.port = portp->portnr;
1632 panelp->ports[i] = portp;
1633 stl_portinit(brdp, panelp, portp);
1634 }
1635
Jiri Slabyc62429d2006-12-08 02:39:14 -08001636 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637}
1638
Jiri Slaby3b85b342006-12-08 02:39:10 -08001639static void stl_cleanup_panels(struct stlbrd *brdp)
1640{
1641 struct stlpanel *panelp;
1642 struct stlport *portp;
1643 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001644 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001645
1646 for (j = 0; j < STL_MAXPANELS; j++) {
1647 panelp = brdp->panels[j];
1648 if (panelp == NULL)
1649 continue;
1650 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1651 portp = panelp->ports[k];
1652 if (portp == NULL)
1653 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001654 tty = tty_port_tty_get(&portp->port);
1655 if (tty != NULL) {
1656 stl_hangup(tty);
1657 tty_kref_put(tty);
1658 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001659 kfree(portp->tx.buf);
1660 kfree(portp);
1661 }
1662 kfree(panelp);
1663 }
1664}
1665
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666/*****************************************************************************/
1667
1668/*
1669 * Try to find and initialize an EasyIO board.
1670 */
1671
Jiri Slaby705c1862006-12-08 02:39:11 -08001672static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001674 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 unsigned int status;
1676 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001677 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
Jiri Slabya0564e12006-12-08 02:38:37 -08001679 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 brdp->ioctrl = brdp->ioaddr1 + 1;
1682 brdp->iostatus = brdp->ioaddr1 + 2;
1683
1684 status = inb(brdp->iostatus);
1685 if ((status & EIO_IDBITMASK) == EIO_MK3)
1686 brdp->ioctrl++;
1687
1688/*
1689 * Handle board specific stuff now. The real difference is PCI
1690 * or not PCI.
1691 */
1692 if (brdp->brdtype == BRD_EASYIOPCI) {
1693 brdp->iosize1 = 0x80;
1694 brdp->iosize2 = 0x80;
1695 name = "serial(EIO-PCI)";
1696 outb(0x41, (brdp->ioaddr2 + 0x4c));
1697 } else {
1698 brdp->iosize1 = 8;
1699 name = "serial(EIO)";
1700 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1701 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1702 printk("STALLION: invalid irq=%d for brd=%d\n",
1703 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001704 retval = -EINVAL;
1705 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 }
1707 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1708 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1709 brdp->ioctrl);
1710 }
1711
Jiri Slaby3b85b342006-12-08 02:39:10 -08001712 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1714 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1715 "%x conflicts with another device\n", brdp->brdnr,
1716 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001717 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 }
1719
1720 if (brdp->iosize2 > 0)
1721 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1722 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1723 "address %x conflicts with another device\n",
1724 brdp->brdnr, brdp->ioaddr2);
1725 printk(KERN_WARNING "STALLION: Warning, also "
1726 "releasing board %d I/O address %x \n",
1727 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001728 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 }
1730
1731/*
1732 * Everything looks OK, so let's go ahead and probe for the hardware.
1733 */
1734 brdp->clk = CD1400_CLK;
1735 brdp->isr = stl_eiointr;
1736
Jiri Slaby3b85b342006-12-08 02:39:10 -08001737 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 switch (status & EIO_IDBITMASK) {
1739 case EIO_8PORTM:
1740 brdp->clk = CD1400_CLK8M;
1741 /* fall thru */
1742 case EIO_8PORTRS:
1743 case EIO_8PORTDI:
1744 brdp->nrports = 8;
1745 break;
1746 case EIO_4PORTRS:
1747 brdp->nrports = 4;
1748 break;
1749 case EIO_MK3:
1750 switch (status & EIO_BRDMASK) {
1751 case ID_BRD4:
1752 brdp->nrports = 4;
1753 break;
1754 case ID_BRD8:
1755 brdp->nrports = 8;
1756 break;
1757 case ID_BRD16:
1758 brdp->nrports = 16;
1759 break;
1760 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001761 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 }
1763 break;
1764 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001765 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 }
1767
1768/*
1769 * We have verified that the board is actually present, so now we
1770 * can complete the setup.
1771 */
1772
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001773 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001774 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001776 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001777 retval = -ENOMEM;
1778 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
1781 panelp->magic = STL_PANELMAGIC;
1782 panelp->brdnr = brdp->brdnr;
1783 panelp->panelnr = 0;
1784 panelp->nrports = brdp->nrports;
1785 panelp->iobase = brdp->ioaddr1;
1786 panelp->hwid = status;
1787 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001788 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 panelp->isr = stl_sc26198intr;
1790 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001791 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 panelp->isr = stl_cd1400eiointr;
1793 }
1794
1795 brdp->panels[0] = panelp;
1796 brdp->nrpanels = 1;
1797 brdp->state |= BRD_FOUND;
1798 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001799 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 printk("STALLION: failed to register interrupt "
1801 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001802 retval = -ENODEV;
1803 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001805
1806 return 0;
1807err_fr:
1808 stl_cleanup_panels(brdp);
1809err_rel2:
1810 if (brdp->iosize2 > 0)
1811 release_region(brdp->ioaddr2, brdp->iosize2);
1812err_rel1:
1813 release_region(brdp->ioaddr1, brdp->iosize1);
1814err:
1815 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816}
1817
1818/*****************************************************************************/
1819
1820/*
1821 * Try to find an ECH board and initialize it. This code is capable of
1822 * dealing with all types of ECH board.
1823 */
1824
Jiri Slaby705c1862006-12-08 02:39:11 -08001825static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001827 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001828 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1829 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 char *name;
1831
Jiri Slabya0564e12006-12-08 02:38:37 -08001832 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
1834 status = 0;
1835 conflict = 0;
1836
1837/*
1838 * Set up the initial board register contents for boards. This varies a
1839 * bit between the different board types. So we need to handle each
1840 * separately. Also do a check that the supplied IRQ is good.
1841 */
1842 switch (brdp->brdtype) {
1843
1844 case BRD_ECH:
1845 brdp->isr = stl_echatintr;
1846 brdp->ioctrl = brdp->ioaddr1 + 1;
1847 brdp->iostatus = brdp->ioaddr1 + 1;
1848 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001849 if ((status & ECH_IDBITMASK) != ECH_ID) {
1850 retval = -ENODEV;
1851 goto err;
1852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1854 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1855 printk("STALLION: invalid irq=%d for brd=%d\n",
1856 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001857 retval = -EINVAL;
1858 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 }
1860 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1861 status |= (stl_vecmap[brdp->irq] << 1);
1862 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1863 brdp->ioctrlval = ECH_INTENABLE |
1864 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001865 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1867 brdp->iosize1 = 2;
1868 brdp->iosize2 = 32;
1869 name = "serial(EC8/32)";
1870 outb(status, brdp->ioaddr1);
1871 break;
1872
1873 case BRD_ECHMC:
1874 brdp->isr = stl_echmcaintr;
1875 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1876 brdp->iostatus = brdp->ioctrl;
1877 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001878 if ((status & ECH_IDBITMASK) != ECH_ID) {
1879 retval = -ENODEV;
1880 goto err;
1881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1883 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1884 printk("STALLION: invalid irq=%d for brd=%d\n",
1885 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001886 retval = -EINVAL;
1887 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 }
1889 outb(ECHMC_BRDRESET, brdp->ioctrl);
1890 outb(ECHMC_INTENABLE, brdp->ioctrl);
1891 brdp->iosize1 = 64;
1892 name = "serial(EC8/32-MC)";
1893 break;
1894
1895 case BRD_ECHPCI:
1896 brdp->isr = stl_echpciintr;
1897 brdp->ioctrl = brdp->ioaddr1 + 2;
1898 brdp->iosize1 = 4;
1899 brdp->iosize2 = 8;
1900 name = "serial(EC8/32-PCI)";
1901 break;
1902
1903 case BRD_ECH64PCI:
1904 brdp->isr = stl_echpci64intr;
1905 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1906 outb(0x43, (brdp->ioaddr1 + 0x4c));
1907 brdp->iosize1 = 0x80;
1908 brdp->iosize2 = 0x80;
1909 name = "serial(EC8/64-PCI)";
1910 break;
1911
1912 default:
1913 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001914 retval = -EINVAL;
1915 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 }
1917
1918/*
1919 * Check boards for possible IO address conflicts and return fail status
1920 * if an IO conflict found.
1921 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001922 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1924 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1925 "%x conflicts with another device\n", brdp->brdnr,
1926 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001927 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 }
1929
1930 if (brdp->iosize2 > 0)
1931 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1932 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1933 "address %x conflicts with another device\n",
1934 brdp->brdnr, brdp->ioaddr2);
1935 printk(KERN_WARNING "STALLION: Warning, also "
1936 "releasing board %d I/O address %x \n",
1937 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001938 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 }
1940
1941/*
1942 * Scan through the secondary io address space looking for panels.
1943 * As we find'em allocate and initialize panel structures for each.
1944 */
1945 brdp->clk = CD1400_CLK;
1946 brdp->hwid = status;
1947
1948 ioaddr = brdp->ioaddr2;
1949 banknr = 0;
1950 panelnr = 0;
1951 nxtid = 0;
1952
Jiri Slabyc62429d2006-12-08 02:39:14 -08001953 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 if (brdp->brdtype == BRD_ECHPCI) {
1955 outb(nxtid, brdp->ioctrl);
1956 ioaddr = brdp->ioaddr2;
1957 }
1958 status = inb(ioaddr + ECH_PNLSTATUS);
1959 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07001960 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001961 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001962 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001964 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07001965 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001966 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 panelp->magic = STL_PANELMAGIC;
1969 panelp->brdnr = brdp->brdnr;
1970 panelp->panelnr = panelnr;
1971 panelp->iobase = ioaddr;
1972 panelp->pagenr = nxtid;
1973 panelp->hwid = status;
1974 brdp->bnk2panel[banknr] = panelp;
1975 brdp->bnkpageaddr[banknr] = nxtid;
1976 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
1977
1978 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001979 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 panelp->isr = stl_sc26198intr;
1981 if (status & ECH_PNL16PORT) {
1982 panelp->nrports = 16;
1983 brdp->bnk2panel[banknr] = panelp;
1984 brdp->bnkpageaddr[banknr] = nxtid;
1985 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
1986 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001987 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001990 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 panelp->isr = stl_cd1400echintr;
1992 if (status & ECH_PNL16PORT) {
1993 panelp->nrports = 16;
1994 panelp->ackmask = 0x80;
1995 if (brdp->brdtype != BRD_ECHPCI)
1996 ioaddr += EREG_BANKSIZE;
1997 brdp->bnk2panel[banknr] = panelp;
1998 brdp->bnkpageaddr[banknr] = ++nxtid;
1999 brdp->bnkstataddr[banknr++] = ioaddr +
2000 ECH_PNLSTATUS;
2001 } else {
2002 panelp->nrports = 8;
2003 panelp->ackmask = 0xc0;
2004 }
2005 }
2006
2007 nxtid++;
2008 ioaddr += EREG_BANKSIZE;
2009 brdp->nrports += panelp->nrports;
2010 brdp->panels[panelnr++] = panelp;
2011 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002012 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2013 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002014 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 }
2017
2018 brdp->nrpanels = panelnr;
2019 brdp->nrbnks = banknr;
2020 if (brdp->brdtype == BRD_ECH)
2021 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2022
2023 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002024 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 printk("STALLION: failed to register interrupt "
2026 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002027 retval = -ENODEV;
2028 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 }
2030
Jiri Slaby3b85b342006-12-08 02:39:10 -08002031 return 0;
2032err_fr:
2033 stl_cleanup_panels(brdp);
2034 if (brdp->iosize2 > 0)
2035 release_region(brdp->ioaddr2, brdp->iosize2);
2036err_rel1:
2037 release_region(brdp->ioaddr1, brdp->iosize1);
2038err:
2039 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040}
2041
2042/*****************************************************************************/
2043
2044/*
2045 * Initialize and configure the specified board.
2046 * Scan through all the boards in the configuration and see what we
2047 * can find. Handle EIO and the ECH boards a little differently here
2048 * since the initial search and setup is very different.
2049 */
2050
Jiri Slaby705c1862006-12-08 02:39:11 -08002051static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002053 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
Jiri Slabya0564e12006-12-08 02:38:37 -08002055 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
2057 switch (brdp->brdtype) {
2058 case BRD_EASYIO:
2059 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002060 retval = stl_initeio(brdp);
2061 if (retval)
2062 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 break;
2064 case BRD_ECH:
2065 case BRD_ECHMC:
2066 case BRD_ECHPCI:
2067 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002068 retval = stl_initech(brdp);
2069 if (retval)
2070 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 break;
2072 default:
2073 printk("STALLION: board=%d is unknown board type=%d\n",
2074 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002075 retval = -ENODEV;
2076 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 }
2078
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 if ((brdp->state & BRD_FOUND) == 0) {
2080 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2081 stl_brdnames[brdp->brdtype], brdp->brdnr,
2082 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002083 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084 }
2085
Jiri Slabyc62429d2006-12-08 02:39:14 -08002086 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002087 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 stl_initports(brdp, brdp->panels[i]);
2089
2090 printk("STALLION: %s found, board=%d io=%x irq=%d "
2091 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2092 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2093 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002094
2095 return 0;
2096err_free:
2097 free_irq(brdp->irq, brdp);
2098
2099 stl_cleanup_panels(brdp);
2100
2101 release_region(brdp->ioaddr1, brdp->iosize1);
2102 if (brdp->iosize2 > 0)
2103 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002104err:
2105 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106}
2107
2108/*****************************************************************************/
2109
2110/*
2111 * Find the next available board number that is free.
2112 */
2113
Jiri Slaby705c1862006-12-08 02:39:11 -08002114static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002116 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Jiri Slabyc62429d2006-12-08 02:39:14 -08002118 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002119 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 if (i >= stl_nrbrds)
2121 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002122 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002124
2125 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126}
2127
2128/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129/*
2130 * We have a Stallion board. Allocate a board structure and
2131 * initialize it. Read its IO and IRQ resources from PCI
2132 * configuration space.
2133 */
2134
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002135static int __devinit stl_pciprobe(struct pci_dev *pdev,
2136 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002138 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002139 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002140 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002142 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002143 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002144
Jiri Slaby3b85b342006-12-08 02:39:10 -08002145 retval = pci_enable_device(pdev);
2146 if (retval)
2147 goto err;
2148 brdp = stl_allocbrd();
2149 if (brdp == NULL) {
2150 retval = -ENOMEM;
2151 goto err;
2152 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002153 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002154 brdnr = stl_getbrdnr();
2155 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002156 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002158 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002159 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002160 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002162 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002163 stl_brds[brdp->brdnr] = brdp;
2164 mutex_unlock(&stl_brdslock);
2165
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002167 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
2169/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 * We have all resources from the board, so let's setup the actual
2171 * board structure now.
2172 */
2173 switch (brdtype) {
2174 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002175 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2176 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 break;
2178 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002179 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2180 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 break;
2182 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002183 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2184 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 break;
2186 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002187 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 break;
2189 }
2190
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002191 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002192 retval = stl_brdinit(brdp);
2193 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002194 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002196 pci_set_drvdata(pdev, brdp);
2197
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002198 for (i = 0; i < brdp->nrports; i++)
2199 tty_register_device(stl_serial,
2200 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2201
Jiri Slaby3b85b342006-12-08 02:39:10 -08002202 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002203err_null:
2204 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002205err_fr:
2206 kfree(brdp);
2207err:
2208 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209}
2210
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002211static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002213 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002214 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002216 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002218 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002220 release_region(brdp->ioaddr1, brdp->iosize1);
2221 if (brdp->iosize2 > 0)
2222 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002224 for (i = 0; i < brdp->nrports; i++)
2225 tty_unregister_device(stl_serial,
2226 brdp->brdnr * STL_MAXPORTS + i);
2227
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002228 stl_brds[brdp->brdnr] = NULL;
2229 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230}
2231
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002232static struct pci_driver stl_pcidriver = {
2233 .name = "stallion",
2234 .id_table = stl_pcibrds,
2235 .probe = stl_pciprobe,
2236 .remove = __devexit_p(stl_pciremove)
2237};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
2239/*****************************************************************************/
2240
2241/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 * Return the board stats structure to user app.
2243 */
2244
2245static int stl_getbrdstats(combrd_t __user *bp)
2246{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002247 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002248 struct stlbrd *brdp;
2249 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002250 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2253 return -EFAULT;
2254 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002255 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002257 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002258 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
2260 memset(&stl_brdstats, 0, sizeof(combrd_t));
2261 stl_brdstats.brd = brdp->brdnr;
2262 stl_brdstats.type = brdp->brdtype;
2263 stl_brdstats.hwid = brdp->hwid;
2264 stl_brdstats.state = brdp->state;
2265 stl_brdstats.ioaddr = brdp->ioaddr1;
2266 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2267 stl_brdstats.irq = brdp->irq;
2268 stl_brdstats.nrpanels = brdp->nrpanels;
2269 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002270 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 panelp = brdp->panels[i];
2272 stl_brdstats.panels[i].panel = i;
2273 stl_brdstats.panels[i].hwid = panelp->hwid;
2274 stl_brdstats.panels[i].nrports = panelp->nrports;
2275 }
2276
2277 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2278}
2279
2280/*****************************************************************************/
2281
2282/*
2283 * Resolve the referenced port number into a port struct pointer.
2284 */
2285
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002286static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002288 struct stlbrd *brdp;
2289 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Jiri Slabyc62429d2006-12-08 02:39:14 -08002291 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2292 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002294 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002295 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002296 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002297 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002299 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002300 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002301 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002302 return NULL;
2303 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304}
2305
2306/*****************************************************************************/
2307
2308/*
2309 * Return the port stats structure to user app. A NULL port struct
2310 * pointer passed in means that we need to find out from the app
2311 * what port to get stats for (used through board control device).
2312 */
2313
Alan Coxd18a7502008-10-13 10:40:07 +01002314static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002316 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 unsigned char *head, *tail;
2318 unsigned long flags;
2319
2320 if (!portp) {
2321 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2322 return -EFAULT;
2323 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2324 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002325 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002326 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 }
2328
2329 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002330 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 portp->stats.hwid = portp->hwid;
2332
2333 portp->stats.ttystate = 0;
2334 portp->stats.cflags = 0;
2335 portp->stats.iflags = 0;
2336 portp->stats.oflags = 0;
2337 portp->stats.lflags = 0;
2338 portp->stats.rxbuffered = 0;
2339
Alan Coxb65b5b52006-06-27 02:54:05 -07002340 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002341 if (tty != NULL && portp->port.tty == tty) {
2342 portp->stats.ttystate = tty->flags;
2343 /* No longer available as a statistic */
2344 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2345 if (tty->termios != NULL) {
2346 portp->stats.cflags = tty->termios->c_cflag;
2347 portp->stats.iflags = tty->termios->c_iflag;
2348 portp->stats.oflags = tty->termios->c_oflag;
2349 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 }
Alan Coxd18a7502008-10-13 10:40:07 +01002351 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002352 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
2354 head = portp->tx.head;
2355 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002356 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2357 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2360
2361 return copy_to_user(cp, &portp->stats,
2362 sizeof(comstats_t)) ? -EFAULT : 0;
2363}
2364
2365/*****************************************************************************/
2366
2367/*
2368 * Clear the port stats structure. We also return it zeroed out...
2369 */
2370
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002371static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002373 comstats_t stl_comstats;
2374
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 if (!portp) {
2376 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2377 return -EFAULT;
2378 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2379 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002380 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002381 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 }
2383
2384 memset(&portp->stats, 0, sizeof(comstats_t));
2385 portp->stats.brd = portp->brdnr;
2386 portp->stats.panel = portp->panelnr;
2387 portp->stats.port = portp->portnr;
2388 return copy_to_user(cp, &portp->stats,
2389 sizeof(comstats_t)) ? -EFAULT : 0;
2390}
2391
2392/*****************************************************************************/
2393
2394/*
2395 * Return the entire driver ports structure to a user app.
2396 */
2397
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002398static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002400 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002401 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002403 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 return -EFAULT;
2405 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2406 stl_dummyport.portnr);
2407 if (!portp)
2408 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002409 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410}
2411
2412/*****************************************************************************/
2413
2414/*
2415 * Return the entire driver board structure to a user app.
2416 */
2417
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002418static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002420 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002421 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002423 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002425 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 return -ENODEV;
2427 brdp = stl_brds[stl_dummybrd.brdnr];
2428 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002429 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002430 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431}
2432
2433/*****************************************************************************/
2434
2435/*
2436 * The "staliomem" device is also required to do some special operations
2437 * on the board and/or ports. In this driver it is mostly used for stats
2438 * collection.
2439 */
2440
Alan Cox894cb912009-10-13 16:34:15 +01002441static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442{
2443 int brdnr, rc;
2444 void __user *argp = (void __user *)arg;
2445
Alan Cox894cb912009-10-13 16:34:15 +01002446 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
Alan Cox894cb912009-10-13 16:34:15 +01002448 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002450 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 rc = 0;
2452
Alan Cox894cb912009-10-13 16:34:15 +01002453 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 switch (cmd) {
2455 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002456 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 break;
2458 case COM_CLRPORTSTATS:
2459 rc = stl_clrportstats(NULL, argp);
2460 break;
2461 case COM_GETBRDSTATS:
2462 rc = stl_getbrdstats(argp);
2463 break;
2464 case COM_READPORT:
2465 rc = stl_getportstruct(argp);
2466 break;
2467 case COM_READBOARD:
2468 rc = stl_getbrdstruct(argp);
2469 break;
2470 default:
2471 rc = -ENOIOCTLCMD;
2472 break;
2473 }
Alan Cox894cb912009-10-13 16:34:15 +01002474 unlock_kernel();
Jiri Slabyc62429d2006-12-08 02:39:14 -08002475 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476}
2477
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002478static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 .open = stl_open,
2480 .close = stl_close,
2481 .write = stl_write,
2482 .put_char = stl_putchar,
2483 .flush_chars = stl_flushchars,
2484 .write_room = stl_writeroom,
2485 .chars_in_buffer = stl_charsinbuffer,
2486 .ioctl = stl_ioctl,
2487 .set_termios = stl_settermios,
2488 .throttle = stl_throttle,
2489 .unthrottle = stl_unthrottle,
2490 .stop = stl_stop,
2491 .start = stl_start,
2492 .hangup = stl_hangup,
2493 .flush_buffer = stl_flushbuffer,
2494 .break_ctl = stl_breakctl,
2495 .wait_until_sent = stl_waituntilsent,
2496 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 .tiocmget = stl_tiocmget,
2498 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002499 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500};
2501
Alan Cox31f35932009-01-02 13:45:05 +00002502static const struct tty_port_operations stl_port_ops = {
2503 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002504 .dtr_rts = stl_dtr_rts,
Alan Cox047e9652009-11-30 13:17:03 +00002505 .activate = stl_activate,
2506 .shutdown = stl_shutdown,
Alan Cox31f35932009-01-02 13:45:05 +00002507};
2508
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510/* CD1400 HARDWARE FUNCTIONS */
2511/*****************************************************************************/
2512
2513/*
2514 * These functions get/set/update the registers of the cd1400 UARTs.
2515 * Access to the cd1400 registers is via an address/data io port pair.
2516 * (Maybe should make this inline...)
2517 */
2518
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002519static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520{
2521 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002522 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523}
2524
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002525static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002527 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 outb(value, portp->ioaddr + EREG_DATA);
2529}
2530
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002531static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002533 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 if (inb(portp->ioaddr + EREG_DATA) != value) {
2535 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002536 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002538 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539}
2540
2541/*****************************************************************************/
2542
2543/*
2544 * Inbitialize the UARTs in a panel. We don't care what sort of board
2545 * these ports are on - since the port io registers are almost
2546 * identical when dealing with ports.
2547 */
2548
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002549static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550{
2551 unsigned int gfrcr;
2552 int chipmask, i, j;
2553 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002554 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
Jiri Slabya0564e12006-12-08 02:38:37 -08002556 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Alan Coxb65b5b52006-06-27 02:54:05 -07002558 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 BRDENABLE(panelp->brdnr, panelp->pagenr);
2560
2561/*
2562 * Check that each chip is present and started up OK.
2563 */
2564 chipmask = 0;
2565 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002566 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 if (brdp->brdtype == BRD_ECHPCI) {
2568 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2569 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002570 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 uartaddr = (i & 0x01) ? 0x080 : 0;
2573 outb((GFRCR + uartaddr), ioaddr);
2574 outb(0, (ioaddr + EREG_DATA));
2575 outb((CCR + uartaddr), ioaddr);
2576 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2577 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2578 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002579 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2581 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002582
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2584 printk("STALLION: cd1400 not responding, "
2585 "brd=%d panel=%d chip=%d\n",
2586 panelp->brdnr, panelp->panelnr, i);
2587 continue;
2588 }
2589 chipmask |= (0x1 << i);
2590 outb((PPR + uartaddr), ioaddr);
2591 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2592 }
2593
2594 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002595 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002596 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597}
2598
2599/*****************************************************************************/
2600
2601/*
2602 * Initialize hardware specific port registers.
2603 */
2604
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002605static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606{
Alan Coxb65b5b52006-06-27 02:54:05 -07002607 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002608 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2609 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Jiri Slaby615e4a72006-12-08 02:38:38 -08002611 if ((brdp == NULL) || (panelp == NULL) ||
2612 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return;
2614
Alan Coxb65b5b52006-06-27 02:54:05 -07002615 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2617 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2618 portp->uartaddr = (portp->portnr & 0x04) << 5;
2619 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2620
2621 BRDENABLE(portp->brdnr, portp->pagenr);
2622 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2623 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2624 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2625 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002626 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627}
2628
2629/*****************************************************************************/
2630
2631/*
2632 * Wait for the command register to be ready. We will poll this,
2633 * since it won't usually take too long to be ready.
2634 */
2635
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002636static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637{
2638 int i;
2639
Jiri Slabyc62429d2006-12-08 02:39:14 -08002640 for (i = 0; i < CCR_MAXWAIT; i++)
2641 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2645 portp->portnr, portp->panelnr, portp->brdnr);
2646}
2647
2648/*****************************************************************************/
2649
2650/*
2651 * Set up the cd1400 registers for a port based on the termios port
2652 * settings.
2653 */
2654
Alan Cox606d0992006-12-08 02:38:45 -08002655static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002657 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 unsigned long flags;
2659 unsigned int clkdiv, baudrate;
2660 unsigned char cor1, cor2, cor3;
2661 unsigned char cor4, cor5, ccr;
2662 unsigned char srer, sreron, sreroff;
2663 unsigned char mcor1, mcor2, rtpr;
2664 unsigned char clk, div;
2665
2666 cor1 = 0;
2667 cor2 = 0;
2668 cor3 = 0;
2669 cor4 = 0;
2670 cor5 = 0;
2671 ccr = 0;
2672 rtpr = 0;
2673 clk = 0;
2674 div = 0;
2675 mcor1 = 0;
2676 mcor2 = 0;
2677 sreron = 0;
2678 sreroff = 0;
2679
2680 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002681 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 return;
2683
2684/*
2685 * Set up the RX char ignore mask with those RX error types we
2686 * can ignore. We can get the cd1400 to help us out a little here,
2687 * it will ignore parity errors and breaks for us.
2688 */
2689 portp->rxignoremsk = 0;
2690 if (tiosp->c_iflag & IGNPAR) {
2691 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2692 cor1 |= COR1_PARIGNORE;
2693 }
2694 if (tiosp->c_iflag & IGNBRK) {
2695 portp->rxignoremsk |= ST_BREAK;
2696 cor4 |= COR4_IGNBRK;
2697 }
2698
2699 portp->rxmarkmsk = ST_OVERRUN;
2700 if (tiosp->c_iflag & (INPCK | PARMRK))
2701 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2702 if (tiosp->c_iflag & BRKINT)
2703 portp->rxmarkmsk |= ST_BREAK;
2704
2705/*
2706 * Go through the char size, parity and stop bits and set all the
2707 * option register appropriately.
2708 */
2709 switch (tiosp->c_cflag & CSIZE) {
2710 case CS5:
2711 cor1 |= COR1_CHL5;
2712 break;
2713 case CS6:
2714 cor1 |= COR1_CHL6;
2715 break;
2716 case CS7:
2717 cor1 |= COR1_CHL7;
2718 break;
2719 default:
2720 cor1 |= COR1_CHL8;
2721 break;
2722 }
2723
2724 if (tiosp->c_cflag & CSTOPB)
2725 cor1 |= COR1_STOP2;
2726 else
2727 cor1 |= COR1_STOP1;
2728
2729 if (tiosp->c_cflag & PARENB) {
2730 if (tiosp->c_cflag & PARODD)
2731 cor1 |= (COR1_PARENB | COR1_PARODD);
2732 else
2733 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2734 } else {
2735 cor1 |= COR1_PARNONE;
2736 }
2737
2738/*
2739 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2740 * space for hardware flow control and the like. This should be set to
2741 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2742 * really be based on VTIME.
2743 */
2744 cor3 |= FIFO_RXTHRESHOLD;
2745 rtpr = 2;
2746
2747/*
2748 * Calculate the baud rate timers. For now we will just assume that
2749 * the input and output baud are the same. Could have used a baud
2750 * table here, but this way we can generate virtually any baud rate
2751 * we like!
2752 */
2753 baudrate = tiosp->c_cflag & CBAUD;
2754 if (baudrate & CBAUDEX) {
2755 baudrate &= ~CBAUDEX;
2756 if ((baudrate < 1) || (baudrate > 4))
2757 tiosp->c_cflag &= ~CBAUDEX;
2758 else
2759 baudrate += 15;
2760 }
2761 baudrate = stl_baudrates[baudrate];
2762 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002763 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002765 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002767 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002769 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002771 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 baudrate = (portp->baud_base / portp->custom_divisor);
2773 }
2774 if (baudrate > STL_CD1400MAXBAUD)
2775 baudrate = STL_CD1400MAXBAUD;
2776
2777 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002778 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2779 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 if (clkdiv < 0x100)
2781 break;
2782 }
2783 div = (unsigned char) clkdiv;
2784 }
2785
2786/*
2787 * Check what form of modem signaling is required and set it up.
2788 */
2789 if ((tiosp->c_cflag & CLOCAL) == 0) {
2790 mcor1 |= MCOR1_DCD;
2791 mcor2 |= MCOR2_DCD;
2792 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002793 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002794 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002795 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
2797/*
2798 * Setup cd1400 enhanced modes if we can. In particular we want to
2799 * handle as much of the flow control as possible automatically. As
2800 * well as saving a few CPU cycles it will also greatly improve flow
2801 * control reliability.
2802 */
2803 if (tiosp->c_iflag & IXON) {
2804 cor2 |= COR2_TXIBE;
2805 cor3 |= COR3_SCD12;
2806 if (tiosp->c_iflag & IXANY)
2807 cor2 |= COR2_IXM;
2808 }
2809
2810 if (tiosp->c_cflag & CRTSCTS) {
2811 cor2 |= COR2_CTSAE;
2812 mcor1 |= FIFO_RTSTHRESHOLD;
2813 }
2814
2815/*
2816 * All cd1400 register values calculated so go through and set
2817 * them all up.
2818 */
2819
Jiri Slabya0564e12006-12-08 02:38:37 -08002820 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002822 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002824 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002826 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2827 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2829 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
Alan Coxb65b5b52006-06-27 02:54:05 -07002831 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 BRDENABLE(portp->brdnr, portp->pagenr);
2833 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2834 srer = stl_cd1400getreg(portp, SRER);
2835 stl_cd1400setreg(portp, SRER, 0);
2836 if (stl_cd1400updatereg(portp, COR1, cor1))
2837 ccr = 1;
2838 if (stl_cd1400updatereg(portp, COR2, cor2))
2839 ccr = 1;
2840 if (stl_cd1400updatereg(portp, COR3, cor3))
2841 ccr = 1;
2842 if (ccr) {
2843 stl_cd1400ccrwait(portp);
2844 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2845 }
2846 stl_cd1400setreg(portp, COR4, cor4);
2847 stl_cd1400setreg(portp, COR5, cor5);
2848 stl_cd1400setreg(portp, MCOR1, mcor1);
2849 stl_cd1400setreg(portp, MCOR2, mcor2);
2850 if (baudrate > 0) {
2851 stl_cd1400setreg(portp, TCOR, clk);
2852 stl_cd1400setreg(portp, TBPR, div);
2853 stl_cd1400setreg(portp, RCOR, clk);
2854 stl_cd1400setreg(portp, RBPR, div);
2855 }
2856 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2857 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2858 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2859 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2860 stl_cd1400setreg(portp, RTPR, rtpr);
2861 mcor1 = stl_cd1400getreg(portp, MSVR1);
2862 if (mcor1 & MSVR1_DCD)
2863 portp->sigs |= TIOCM_CD;
2864 else
2865 portp->sigs &= ~TIOCM_CD;
2866 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2867 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002868 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869}
2870
2871/*****************************************************************************/
2872
2873/*
2874 * Set the state of the DTR and RTS signals.
2875 */
2876
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002877static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878{
2879 unsigned char msvr1, msvr2;
2880 unsigned long flags;
2881
Jiri Slabya0564e12006-12-08 02:38:37 -08002882 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2883 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884
2885 msvr1 = 0;
2886 msvr2 = 0;
2887 if (dtr > 0)
2888 msvr1 = MSVR1_DTR;
2889 if (rts > 0)
2890 msvr2 = MSVR2_RTS;
2891
Alan Coxb65b5b52006-06-27 02:54:05 -07002892 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 BRDENABLE(portp->brdnr, portp->pagenr);
2894 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2895 if (rts >= 0)
2896 stl_cd1400setreg(portp, MSVR2, msvr2);
2897 if (dtr >= 0)
2898 stl_cd1400setreg(portp, MSVR1, msvr1);
2899 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002900 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901}
2902
2903/*****************************************************************************/
2904
2905/*
2906 * Return the state of the signals.
2907 */
2908
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002909static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910{
2911 unsigned char msvr1, msvr2;
2912 unsigned long flags;
2913 int sigs;
2914
Jiri Slabya0564e12006-12-08 02:38:37 -08002915 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
Alan Coxb65b5b52006-06-27 02:54:05 -07002917 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 BRDENABLE(portp->brdnr, portp->pagenr);
2919 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2920 msvr1 = stl_cd1400getreg(portp, MSVR1);
2921 msvr2 = stl_cd1400getreg(portp, MSVR2);
2922 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002923 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924
2925 sigs = 0;
2926 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2927 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2928 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2929 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2930#if 0
2931 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2932 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2933#else
2934 sigs |= TIOCM_DSR;
2935#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002936 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937}
2938
2939/*****************************************************************************/
2940
2941/*
2942 * Enable/Disable the Transmitter and/or Receiver.
2943 */
2944
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002945static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946{
2947 unsigned char ccr;
2948 unsigned long flags;
2949
Jiri Slabya0564e12006-12-08 02:38:37 -08002950 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2951
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 ccr = 0;
2953
2954 if (tx == 0)
2955 ccr |= CCR_TXDISABLE;
2956 else if (tx > 0)
2957 ccr |= CCR_TXENABLE;
2958 if (rx == 0)
2959 ccr |= CCR_RXDISABLE;
2960 else if (rx > 0)
2961 ccr |= CCR_RXENABLE;
2962
Alan Coxb65b5b52006-06-27 02:54:05 -07002963 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 BRDENABLE(portp->brdnr, portp->pagenr);
2965 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2966 stl_cd1400ccrwait(portp);
2967 stl_cd1400setreg(portp, CCR, ccr);
2968 stl_cd1400ccrwait(portp);
2969 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002970 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971}
2972
2973/*****************************************************************************/
2974
2975/*
2976 * Start/stop the Transmitter and/or Receiver.
2977 */
2978
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002979static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980{
2981 unsigned char sreron, sreroff;
2982 unsigned long flags;
2983
Jiri Slabya0564e12006-12-08 02:38:37 -08002984 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
2986 sreron = 0;
2987 sreroff = 0;
2988 if (tx == 0)
2989 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
2990 else if (tx == 1)
2991 sreron |= SRER_TXDATA;
2992 else if (tx >= 2)
2993 sreron |= SRER_TXEMPTY;
2994 if (rx == 0)
2995 sreroff |= SRER_RXDATA;
2996 else if (rx > 0)
2997 sreron |= SRER_RXDATA;
2998
Alan Coxb65b5b52006-06-27 02:54:05 -07002999 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 BRDENABLE(portp->brdnr, portp->pagenr);
3001 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3002 stl_cd1400setreg(portp, SRER,
3003 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3004 BRDDISABLE(portp->brdnr);
3005 if (tx > 0)
3006 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003007 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008}
3009
3010/*****************************************************************************/
3011
3012/*
3013 * Disable all interrupts from this port.
3014 */
3015
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003016static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017{
3018 unsigned long flags;
3019
Jiri Slabya0564e12006-12-08 02:38:37 -08003020 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3021
Alan Coxb65b5b52006-06-27 02:54:05 -07003022 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 BRDENABLE(portp->brdnr, portp->pagenr);
3024 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3025 stl_cd1400setreg(portp, SRER, 0);
3026 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003027 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028}
3029
3030/*****************************************************************************/
3031
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003032static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033{
3034 unsigned long flags;
3035
Jiri Slabya0564e12006-12-08 02:38:37 -08003036 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
Alan Coxb65b5b52006-06-27 02:54:05 -07003038 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 BRDENABLE(portp->brdnr, portp->pagenr);
3040 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3041 stl_cd1400setreg(portp, SRER,
3042 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3043 SRER_TXEMPTY));
3044 BRDDISABLE(portp->brdnr);
3045 portp->brklen = len;
3046 if (len == 1)
3047 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003048 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049}
3050
3051/*****************************************************************************/
3052
3053/*
3054 * Take flow control actions...
3055 */
3056
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003057static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058{
3059 struct tty_struct *tty;
3060 unsigned long flags;
3061
Jiri Slabya0564e12006-12-08 02:38:37 -08003062 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Jiri Slaby615e4a72006-12-08 02:38:38 -08003064 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003066 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003067 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 return;
3069
Alan Coxb65b5b52006-06-27 02:54:05 -07003070 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 BRDENABLE(portp->brdnr, portp->pagenr);
3072 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3073
3074 if (state) {
3075 if (tty->termios->c_iflag & IXOFF) {
3076 stl_cd1400ccrwait(portp);
3077 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3078 portp->stats.rxxon++;
3079 stl_cd1400ccrwait(portp);
3080 }
3081/*
3082 * Question: should we return RTS to what it was before? It may
3083 * have been set by an ioctl... Suppose not, since if you have
3084 * hardware flow control set then it is pretty silly to go and
3085 * set the RTS line by hand.
3086 */
3087 if (tty->termios->c_cflag & CRTSCTS) {
3088 stl_cd1400setreg(portp, MCOR1,
3089 (stl_cd1400getreg(portp, MCOR1) |
3090 FIFO_RTSTHRESHOLD));
3091 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3092 portp->stats.rxrtson++;
3093 }
3094 } else {
3095 if (tty->termios->c_iflag & IXOFF) {
3096 stl_cd1400ccrwait(portp);
3097 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3098 portp->stats.rxxoff++;
3099 stl_cd1400ccrwait(portp);
3100 }
3101 if (tty->termios->c_cflag & CRTSCTS) {
3102 stl_cd1400setreg(portp, MCOR1,
3103 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3104 stl_cd1400setreg(portp, MSVR2, 0);
3105 portp->stats.rxrtsoff++;
3106 }
3107 }
3108
3109 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003110 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003111 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112}
3113
3114/*****************************************************************************/
3115
3116/*
3117 * Send a flow control character...
3118 */
3119
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003120static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121{
3122 struct tty_struct *tty;
3123 unsigned long flags;
3124
Jiri Slabya0564e12006-12-08 02:38:37 -08003125 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Jiri Slaby615e4a72006-12-08 02:38:38 -08003127 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003129 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003130 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 return;
3132
Alan Coxb65b5b52006-06-27 02:54:05 -07003133 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 BRDENABLE(portp->brdnr, portp->pagenr);
3135 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3136 if (state) {
3137 stl_cd1400ccrwait(portp);
3138 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3139 portp->stats.rxxon++;
3140 stl_cd1400ccrwait(portp);
3141 } else {
3142 stl_cd1400ccrwait(portp);
3143 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3144 portp->stats.rxxoff++;
3145 stl_cd1400ccrwait(portp);
3146 }
3147 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003148 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003149 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150}
3151
3152/*****************************************************************************/
3153
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003154static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155{
3156 unsigned long flags;
3157
Jiri Slabya0564e12006-12-08 02:38:37 -08003158 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
Jiri Slaby615e4a72006-12-08 02:38:38 -08003160 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 return;
3162
Alan Coxb65b5b52006-06-27 02:54:05 -07003163 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 BRDENABLE(portp->brdnr, portp->pagenr);
3165 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3166 stl_cd1400ccrwait(portp);
3167 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3168 stl_cd1400ccrwait(portp);
3169 portp->tx.tail = portp->tx.head;
3170 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003171 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172}
3173
3174/*****************************************************************************/
3175
3176/*
3177 * Return the current state of data flow on this port. This is only
3178 * really interresting when determining if data has fully completed
3179 * transmission or not... This is easy for the cd1400, it accurately
3180 * maintains the busy port flag.
3181 */
3182
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003183static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184{
Jiri Slabya0564e12006-12-08 02:38:37 -08003185 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
Jiri Slaby615e4a72006-12-08 02:38:38 -08003187 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003188 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189
Jesper Juhl014c2542006-01-15 02:37:08 +01003190 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191}
3192
3193/*****************************************************************************/
3194
3195/*
3196 * Interrupt service routine for cd1400 EasyIO boards.
3197 */
3198
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003199static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200{
3201 unsigned char svrtype;
3202
Jiri Slabya0564e12006-12-08 02:38:37 -08003203 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Alan Coxb65b5b52006-06-27 02:54:05 -07003205 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 outb(SVRR, iobase);
3207 svrtype = inb(iobase + EREG_DATA);
3208 if (panelp->nrports > 4) {
3209 outb((SVRR + 0x80), iobase);
3210 svrtype |= inb(iobase + EREG_DATA);
3211 }
3212
3213 if (svrtype & SVRR_RX)
3214 stl_cd1400rxisr(panelp, iobase);
3215 else if (svrtype & SVRR_TX)
3216 stl_cd1400txisr(panelp, iobase);
3217 else if (svrtype & SVRR_MDM)
3218 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003219
3220 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221}
3222
3223/*****************************************************************************/
3224
3225/*
3226 * Interrupt service routine for cd1400 panels.
3227 */
3228
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003229static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230{
3231 unsigned char svrtype;
3232
Jiri Slabya0564e12006-12-08 02:38:37 -08003233 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234
3235 outb(SVRR, iobase);
3236 svrtype = inb(iobase + EREG_DATA);
3237 outb((SVRR + 0x80), iobase);
3238 svrtype |= inb(iobase + EREG_DATA);
3239 if (svrtype & SVRR_RX)
3240 stl_cd1400rxisr(panelp, iobase);
3241 else if (svrtype & SVRR_TX)
3242 stl_cd1400txisr(panelp, iobase);
3243 else if (svrtype & SVRR_MDM)
3244 stl_cd1400mdmisr(panelp, iobase);
3245}
3246
3247
3248/*****************************************************************************/
3249
3250/*
3251 * Unfortunately we need to handle breaks in the TX data stream, since
3252 * this is the only way to generate them on the cd1400.
3253 */
3254
Jiri Slaby60be4812006-12-08 02:38:40 -08003255static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256{
3257 if (portp->brklen == 1) {
3258 outb((COR2 + portp->uartaddr), ioaddr);
3259 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3260 (ioaddr + EREG_DATA));
3261 outb((TDR + portp->uartaddr), ioaddr);
3262 outb(ETC_CMD, (ioaddr + EREG_DATA));
3263 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3264 outb((SRER + portp->uartaddr), ioaddr);
3265 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3266 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003267 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 } else if (portp->brklen > 1) {
3269 outb((TDR + portp->uartaddr), ioaddr);
3270 outb(ETC_CMD, (ioaddr + EREG_DATA));
3271 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3272 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003273 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 } else {
3275 outb((COR2 + portp->uartaddr), ioaddr);
3276 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3277 (ioaddr + EREG_DATA));
3278 portp->brklen = 0;
3279 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003280 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281}
3282
3283/*****************************************************************************/
3284
3285/*
3286 * Transmit interrupt handler. This has gotta be fast! Handling TX
3287 * chars is pretty simple, stuff as many as possible from the TX buffer
3288 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3289 * are embedded as commands in the data stream. Oh no, had to use a goto!
3290 * This could be optimized more, will do when I get time...
3291 * In practice it is possible that interrupts are enabled but that the
3292 * port has been hung up. Need to handle not having any TX buffer here,
3293 * this is done by using the side effect that head and tail will also
3294 * be NULL if the buffer has been freed.
3295 */
3296
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003297static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003299 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 int len, stlen;
3301 char *head, *tail;
3302 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003303 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Jiri Slabya0564e12006-12-08 02:38:37 -08003305 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
3307 ioack = inb(ioaddr + EREG_TXACK);
3308 if (((ioack & panelp->ackmask) != 0) ||
3309 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3310 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3311 return;
3312 }
3313 portp = panelp->ports[(ioack >> 3)];
3314
3315/*
3316 * Unfortunately we need to handle breaks in the data stream, since
3317 * this is the only way to generate them on the cd1400. Do it now if
3318 * a break is to be sent.
3319 */
3320 if (portp->brklen != 0)
3321 if (stl_cd1400breakisr(portp, ioaddr))
3322 goto stl_txalldone;
3323
3324 head = portp->tx.head;
3325 tail = portp->tx.tail;
3326 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3327 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3328 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3329 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003330 tty = tty_port_tty_get(&portp->port);
3331 if (tty) {
3332 tty_wakeup(tty);
3333 tty_kref_put(tty);
3334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 }
3336
3337 if (len == 0) {
3338 outb((SRER + portp->uartaddr), ioaddr);
3339 srer = inb(ioaddr + EREG_DATA);
3340 if (srer & SRER_TXDATA) {
3341 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3342 } else {
3343 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3344 clear_bit(ASYI_TXBUSY, &portp->istate);
3345 }
3346 outb(srer, (ioaddr + EREG_DATA));
3347 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003348 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003350 stlen = min_t(unsigned int, len,
3351 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352 outb((TDR + portp->uartaddr), ioaddr);
3353 outsb((ioaddr + EREG_DATA), tail, stlen);
3354 len -= stlen;
3355 tail += stlen;
3356 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3357 tail = portp->tx.buf;
3358 if (len > 0) {
3359 outsb((ioaddr + EREG_DATA), tail, len);
3360 tail += len;
3361 }
3362 portp->tx.tail = tail;
3363 }
3364
3365stl_txalldone:
3366 outb((EOSRR + portp->uartaddr), ioaddr);
3367 outb(0, (ioaddr + EREG_DATA));
3368}
3369
3370/*****************************************************************************/
3371
3372/*
3373 * Receive character interrupt handler. Determine if we have good chars
3374 * or bad chars and then process appropriately. Good chars are easy
3375 * just shove the lot into the RX buffer and set all status byte to 0.
3376 * If a bad RX char then process as required. This routine needs to be
3377 * fast! In practice it is possible that we get an interrupt on a port
3378 * that is closed. This can happen on hangups - since they completely
3379 * shutdown a port not in user context. Need to handle this case.
3380 */
3381
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003382static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003384 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 struct tty_struct *tty;
3386 unsigned int ioack, len, buflen;
3387 unsigned char status;
3388 char ch;
3389
Jiri Slabya0564e12006-12-08 02:38:37 -08003390 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
3392 ioack = inb(ioaddr + EREG_RXACK);
3393 if ((ioack & panelp->ackmask) != 0) {
3394 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3395 return;
3396 }
3397 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003398 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399
3400 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3401 outb((RDCR + portp->uartaddr), ioaddr);
3402 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003403 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003404 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 outb((RDSR + portp->uartaddr), ioaddr);
3406 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3407 portp->stats.rxlost += len;
3408 portp->stats.rxtotal += len;
3409 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003410 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003412 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003414 tty_prepare_flip_string(tty, &ptr, len);
3415 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 tty_schedule_flip(tty);
3417 portp->stats.rxtotal += len;
3418 }
3419 }
3420 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3421 outb((RDSR + portp->uartaddr), ioaddr);
3422 status = inb(ioaddr + EREG_DATA);
3423 ch = inb(ioaddr + EREG_DATA);
3424 if (status & ST_PARITY)
3425 portp->stats.rxparity++;
3426 if (status & ST_FRAMING)
3427 portp->stats.rxframing++;
3428 if (status & ST_OVERRUN)
3429 portp->stats.rxoverrun++;
3430 if (status & ST_BREAK)
3431 portp->stats.rxbreaks++;
3432 if (status & ST_SCHARMASK) {
3433 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3434 portp->stats.txxon++;
3435 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3436 portp->stats.txxoff++;
3437 goto stl_rxalldone;
3438 }
Alan Cox33f0f882006-01-09 20:54:13 -08003439 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440 if (portp->rxmarkmsk & status) {
3441 if (status & ST_BREAK) {
3442 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003443 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 do_SAK(tty);
3445 BRDENABLE(portp->brdnr, portp->pagenr);
3446 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003447 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003449 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003451 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003453 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003455 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003457 tty_insert_flip_char(tty, ch, status);
3458 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 }
3460 } else {
3461 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003462 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 return;
3464 }
3465
3466stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003467 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 outb((EOSRR + portp->uartaddr), ioaddr);
3469 outb(0, (ioaddr + EREG_DATA));
3470}
3471
3472/*****************************************************************************/
3473
3474/*
3475 * Modem interrupt handler. The is called when the modem signal line
3476 * (DCD) has changed state. Leave most of the work to the off-level
3477 * processing routine.
3478 */
3479
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003480static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003482 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 unsigned int ioack;
3484 unsigned char misr;
3485
Jiri Slabya0564e12006-12-08 02:38:37 -08003486 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487
3488 ioack = inb(ioaddr + EREG_MDACK);
3489 if (((ioack & panelp->ackmask) != 0) ||
3490 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3491 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3492 return;
3493 }
3494 portp = panelp->ports[(ioack >> 3)];
3495
3496 outb((MISR + portp->uartaddr), ioaddr);
3497 misr = inb(ioaddr + EREG_DATA);
3498 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003499 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 portp->stats.modem++;
3501 }
3502
3503 outb((EOSRR + portp->uartaddr), ioaddr);
3504 outb(0, (ioaddr + EREG_DATA));
3505}
3506
3507/*****************************************************************************/
3508/* SC26198 HARDWARE FUNCTIONS */
3509/*****************************************************************************/
3510
3511/*
3512 * These functions get/set/update the registers of the sc26198 UARTs.
3513 * Access to the sc26198 registers is via an address/data io port pair.
3514 * (Maybe should make this inline...)
3515 */
3516
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003517static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518{
3519 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003520 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521}
3522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003523static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524{
3525 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3526 outb(value, (portp->ioaddr + XP_DATA));
3527}
3528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003529static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530{
3531 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3532 if (inb(portp->ioaddr + XP_DATA) != value) {
3533 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003534 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003536 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537}
3538
3539/*****************************************************************************/
3540
3541/*
3542 * Functions to get and set the sc26198 global registers.
3543 */
3544
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003545static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546{
3547 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003548 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549}
3550
3551#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003552static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553{
3554 outb(regnr, (portp->ioaddr + XP_ADDR));
3555 outb(value, (portp->ioaddr + XP_DATA));
3556}
3557#endif
3558
3559/*****************************************************************************/
3560
3561/*
3562 * Inbitialize the UARTs in a panel. We don't care what sort of board
3563 * these ports are on - since the port io registers are almost
3564 * identical when dealing with ports.
3565 */
3566
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003567static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568{
3569 int chipmask, i;
3570 int nrchips, ioaddr;
3571
Jiri Slabya0564e12006-12-08 02:38:37 -08003572 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573
3574 BRDENABLE(panelp->brdnr, panelp->pagenr);
3575
3576/*
3577 * Check that each chip is present and started up OK.
3578 */
3579 chipmask = 0;
3580 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3581 if (brdp->brdtype == BRD_ECHPCI)
3582 outb(panelp->pagenr, brdp->ioctrl);
3583
Jiri Slabyc62429d2006-12-08 02:39:14 -08003584 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585 ioaddr = panelp->iobase + (i * 4);
3586 outb(SCCR, (ioaddr + XP_ADDR));
3587 outb(CR_RESETALL, (ioaddr + XP_DATA));
3588 outb(TSTR, (ioaddr + XP_ADDR));
3589 if (inb(ioaddr + XP_DATA) != 0) {
3590 printk("STALLION: sc26198 not responding, "
3591 "brd=%d panel=%d chip=%d\n",
3592 panelp->brdnr, panelp->panelnr, i);
3593 continue;
3594 }
3595 chipmask |= (0x1 << i);
3596 outb(GCCR, (ioaddr + XP_ADDR));
3597 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3598 outb(WDTRCR, (ioaddr + XP_ADDR));
3599 outb(0xff, (ioaddr + XP_DATA));
3600 }
3601
3602 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003603 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604}
3605
3606/*****************************************************************************/
3607
3608/*
3609 * Initialize hardware specific port registers.
3610 */
3611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003612static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613{
Jiri Slabya0564e12006-12-08 02:38:37 -08003614 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3615 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616
Jiri Slaby615e4a72006-12-08 02:38:38 -08003617 if ((brdp == NULL) || (panelp == NULL) ||
3618 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 return;
3620
3621 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3622 portp->uartaddr = (portp->portnr & 0x07) << 4;
3623 portp->pagenr = panelp->pagenr;
3624 portp->hwid = 0x1;
3625
3626 BRDENABLE(portp->brdnr, portp->pagenr);
3627 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3628 BRDDISABLE(portp->brdnr);
3629}
3630
3631/*****************************************************************************/
3632
3633/*
3634 * Set up the sc26198 registers for a port based on the termios port
3635 * settings.
3636 */
3637
Alan Cox606d0992006-12-08 02:38:45 -08003638static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003640 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 unsigned long flags;
3642 unsigned int baudrate;
3643 unsigned char mr0, mr1, mr2, clk;
3644 unsigned char imron, imroff, iopr, ipr;
3645
3646 mr0 = 0;
3647 mr1 = 0;
3648 mr2 = 0;
3649 clk = 0;
3650 iopr = 0;
3651 imron = 0;
3652 imroff = 0;
3653
3654 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003655 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 return;
3657
3658/*
3659 * Set up the RX char ignore mask with those RX error types we
3660 * can ignore.
3661 */
3662 portp->rxignoremsk = 0;
3663 if (tiosp->c_iflag & IGNPAR)
3664 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3665 SR_RXOVERRUN);
3666 if (tiosp->c_iflag & IGNBRK)
3667 portp->rxignoremsk |= SR_RXBREAK;
3668
3669 portp->rxmarkmsk = SR_RXOVERRUN;
3670 if (tiosp->c_iflag & (INPCK | PARMRK))
3671 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3672 if (tiosp->c_iflag & BRKINT)
3673 portp->rxmarkmsk |= SR_RXBREAK;
3674
3675/*
3676 * Go through the char size, parity and stop bits and set all the
3677 * option register appropriately.
3678 */
3679 switch (tiosp->c_cflag & CSIZE) {
3680 case CS5:
3681 mr1 |= MR1_CS5;
3682 break;
3683 case CS6:
3684 mr1 |= MR1_CS6;
3685 break;
3686 case CS7:
3687 mr1 |= MR1_CS7;
3688 break;
3689 default:
3690 mr1 |= MR1_CS8;
3691 break;
3692 }
3693
3694 if (tiosp->c_cflag & CSTOPB)
3695 mr2 |= MR2_STOP2;
3696 else
3697 mr2 |= MR2_STOP1;
3698
3699 if (tiosp->c_cflag & PARENB) {
3700 if (tiosp->c_cflag & PARODD)
3701 mr1 |= (MR1_PARENB | MR1_PARODD);
3702 else
3703 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003704 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
3707 mr1 |= MR1_ERRBLOCK;
3708
3709/*
3710 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3711 * space for hardware flow control and the like. This should be set to
3712 * VMIN.
3713 */
3714 mr2 |= MR2_RXFIFOHALF;
3715
3716/*
3717 * Calculate the baud rate timers. For now we will just assume that
3718 * the input and output baud are the same. The sc26198 has a fixed
3719 * baud rate table, so only discrete baud rates possible.
3720 */
3721 baudrate = tiosp->c_cflag & CBAUD;
3722 if (baudrate & CBAUDEX) {
3723 baudrate &= ~CBAUDEX;
3724 if ((baudrate < 1) || (baudrate > 4))
3725 tiosp->c_cflag &= ~CBAUDEX;
3726 else
3727 baudrate += 15;
3728 }
3729 baudrate = stl_baudrates[baudrate];
3730 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003731 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003733 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003735 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003737 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003739 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 baudrate = (portp->baud_base / portp->custom_divisor);
3741 }
3742 if (baudrate > STL_SC26198MAXBAUD)
3743 baudrate = STL_SC26198MAXBAUD;
3744
Jiri Slabyc62429d2006-12-08 02:39:14 -08003745 if (baudrate > 0)
3746 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 if (baudrate <= sc26198_baudtable[clk])
3748 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
3750/*
3751 * Check what form of modem signaling is required and set it up.
3752 */
3753 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003754 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 } else {
3756 iopr |= IOPR_DCDCOS;
3757 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003758 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 }
3760
3761/*
3762 * Setup sc26198 enhanced modes if we can. In particular we want to
3763 * handle as much of the flow control as possible automatically. As
3764 * well as saving a few CPU cycles it will also greatly improve flow
3765 * control reliability.
3766 */
3767 if (tiosp->c_iflag & IXON) {
3768 mr0 |= MR0_SWFTX | MR0_SWFT;
3769 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003770 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003772
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 if (tiosp->c_iflag & IXOFF)
3774 mr0 |= MR0_SWFRX;
3775
3776 if (tiosp->c_cflag & CRTSCTS) {
3777 mr2 |= MR2_AUTOCTS;
3778 mr1 |= MR1_AUTORTS;
3779 }
3780
3781/*
3782 * All sc26198 register values calculated so go through and set
3783 * them all up.
3784 */
3785
Jiri Slabya0564e12006-12-08 02:38:37 -08003786 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003788 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3789 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3790 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3792 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793
Alan Coxb65b5b52006-06-27 02:54:05 -07003794 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 BRDENABLE(portp->brdnr, portp->pagenr);
3796 stl_sc26198setreg(portp, IMR, 0);
3797 stl_sc26198updatereg(portp, MR0, mr0);
3798 stl_sc26198updatereg(portp, MR1, mr1);
3799 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3800 stl_sc26198updatereg(portp, MR2, mr2);
3801 stl_sc26198updatereg(portp, IOPIOR,
3802 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3803
3804 if (baudrate > 0) {
3805 stl_sc26198setreg(portp, TXCSR, clk);
3806 stl_sc26198setreg(portp, RXCSR, clk);
3807 }
3808
3809 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3810 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3811
3812 ipr = stl_sc26198getreg(portp, IPR);
3813 if (ipr & IPR_DCD)
3814 portp->sigs &= ~TIOCM_CD;
3815 else
3816 portp->sigs |= TIOCM_CD;
3817
3818 portp->imr = (portp->imr & ~imroff) | imron;
3819 stl_sc26198setreg(portp, IMR, portp->imr);
3820 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003821 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822}
3823
3824/*****************************************************************************/
3825
3826/*
3827 * Set the state of the DTR and RTS signals.
3828 */
3829
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003830static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831{
3832 unsigned char iopioron, iopioroff;
3833 unsigned long flags;
3834
Jiri Slabya0564e12006-12-08 02:38:37 -08003835 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3836 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
3838 iopioron = 0;
3839 iopioroff = 0;
3840 if (dtr == 0)
3841 iopioroff |= IPR_DTR;
3842 else if (dtr > 0)
3843 iopioron |= IPR_DTR;
3844 if (rts == 0)
3845 iopioroff |= IPR_RTS;
3846 else if (rts > 0)
3847 iopioron |= IPR_RTS;
3848
Alan Coxb65b5b52006-06-27 02:54:05 -07003849 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 BRDENABLE(portp->brdnr, portp->pagenr);
3851 stl_sc26198setreg(portp, IOPIOR,
3852 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3853 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003854 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855}
3856
3857/*****************************************************************************/
3858
3859/*
3860 * Return the state of the signals.
3861 */
3862
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003863static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864{
3865 unsigned char ipr;
3866 unsigned long flags;
3867 int sigs;
3868
Jiri Slabya0564e12006-12-08 02:38:37 -08003869 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Alan Coxb65b5b52006-06-27 02:54:05 -07003871 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 BRDENABLE(portp->brdnr, portp->pagenr);
3873 ipr = stl_sc26198getreg(portp, IPR);
3874 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003875 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
3877 sigs = 0;
3878 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3879 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3880 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3881 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3882 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003883 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884}
3885
3886/*****************************************************************************/
3887
3888/*
3889 * Enable/Disable the Transmitter and/or Receiver.
3890 */
3891
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003892static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893{
3894 unsigned char ccr;
3895 unsigned long flags;
3896
Jiri Slabya0564e12006-12-08 02:38:37 -08003897 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898
3899 ccr = portp->crenable;
3900 if (tx == 0)
3901 ccr &= ~CR_TXENABLE;
3902 else if (tx > 0)
3903 ccr |= CR_TXENABLE;
3904 if (rx == 0)
3905 ccr &= ~CR_RXENABLE;
3906 else if (rx > 0)
3907 ccr |= CR_RXENABLE;
3908
Alan Coxb65b5b52006-06-27 02:54:05 -07003909 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 BRDENABLE(portp->brdnr, portp->pagenr);
3911 stl_sc26198setreg(portp, SCCR, ccr);
3912 BRDDISABLE(portp->brdnr);
3913 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003914 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915}
3916
3917/*****************************************************************************/
3918
3919/*
3920 * Start/stop the Transmitter and/or Receiver.
3921 */
3922
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003923static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924{
3925 unsigned char imr;
3926 unsigned long flags;
3927
Jiri Slabya0564e12006-12-08 02:38:37 -08003928 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
3930 imr = portp->imr;
3931 if (tx == 0)
3932 imr &= ~IR_TXRDY;
3933 else if (tx == 1)
3934 imr |= IR_TXRDY;
3935 if (rx == 0)
3936 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3937 else if (rx > 0)
3938 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3939
Alan Coxb65b5b52006-06-27 02:54:05 -07003940 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 BRDENABLE(portp->brdnr, portp->pagenr);
3942 stl_sc26198setreg(portp, IMR, imr);
3943 BRDDISABLE(portp->brdnr);
3944 portp->imr = imr;
3945 if (tx > 0)
3946 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003947 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948}
3949
3950/*****************************************************************************/
3951
3952/*
3953 * Disable all interrupts from this port.
3954 */
3955
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003956static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957{
3958 unsigned long flags;
3959
Jiri Slabya0564e12006-12-08 02:38:37 -08003960 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Alan Coxb65b5b52006-06-27 02:54:05 -07003962 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 BRDENABLE(portp->brdnr, portp->pagenr);
3964 portp->imr = 0;
3965 stl_sc26198setreg(portp, IMR, 0);
3966 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003967 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968}
3969
3970/*****************************************************************************/
3971
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003972static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973{
3974 unsigned long flags;
3975
Jiri Slabya0564e12006-12-08 02:38:37 -08003976 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Alan Coxb65b5b52006-06-27 02:54:05 -07003978 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 BRDENABLE(portp->brdnr, portp->pagenr);
3980 if (len == 1) {
3981 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
3982 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003983 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003985
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003987 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988}
3989
3990/*****************************************************************************/
3991
3992/*
3993 * Take flow control actions...
3994 */
3995
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003996static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997{
3998 struct tty_struct *tty;
3999 unsigned long flags;
4000 unsigned char mr0;
4001
Jiri Slabya0564e12006-12-08 02:38:37 -08004002 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003
Jiri Slaby615e4a72006-12-08 02:38:38 -08004004 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004006 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004007 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008 return;
4009
Alan Coxb65b5b52006-06-27 02:54:05 -07004010 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 BRDENABLE(portp->brdnr, portp->pagenr);
4012
4013 if (state) {
4014 if (tty->termios->c_iflag & IXOFF) {
4015 mr0 = stl_sc26198getreg(portp, MR0);
4016 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4017 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4018 mr0 |= MR0_SWFRX;
4019 portp->stats.rxxon++;
4020 stl_sc26198wait(portp);
4021 stl_sc26198setreg(portp, MR0, mr0);
4022 }
4023/*
4024 * Question: should we return RTS to what it was before? It may
4025 * have been set by an ioctl... Suppose not, since if you have
4026 * hardware flow control set then it is pretty silly to go and
4027 * set the RTS line by hand.
4028 */
4029 if (tty->termios->c_cflag & CRTSCTS) {
4030 stl_sc26198setreg(portp, MR1,
4031 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4032 stl_sc26198setreg(portp, IOPIOR,
4033 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4034 portp->stats.rxrtson++;
4035 }
4036 } else {
4037 if (tty->termios->c_iflag & IXOFF) {
4038 mr0 = stl_sc26198getreg(portp, MR0);
4039 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4040 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4041 mr0 &= ~MR0_SWFRX;
4042 portp->stats.rxxoff++;
4043 stl_sc26198wait(portp);
4044 stl_sc26198setreg(portp, MR0, mr0);
4045 }
4046 if (tty->termios->c_cflag & CRTSCTS) {
4047 stl_sc26198setreg(portp, MR1,
4048 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4049 stl_sc26198setreg(portp, IOPIOR,
4050 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4051 portp->stats.rxrtsoff++;
4052 }
4053 }
4054
4055 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004056 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004057 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
4059
4060/*****************************************************************************/
4061
4062/*
4063 * Send a flow control character.
4064 */
4065
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004066static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
4068 struct tty_struct *tty;
4069 unsigned long flags;
4070 unsigned char mr0;
4071
Jiri Slabya0564e12006-12-08 02:38:37 -08004072 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Jiri Slaby615e4a72006-12-08 02:38:38 -08004074 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004076 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004077 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078 return;
4079
Alan Coxb65b5b52006-06-27 02:54:05 -07004080 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 BRDENABLE(portp->brdnr, portp->pagenr);
4082 if (state) {
4083 mr0 = stl_sc26198getreg(portp, MR0);
4084 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4085 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4086 mr0 |= MR0_SWFRX;
4087 portp->stats.rxxon++;
4088 stl_sc26198wait(portp);
4089 stl_sc26198setreg(portp, MR0, mr0);
4090 } else {
4091 mr0 = stl_sc26198getreg(portp, MR0);
4092 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4093 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4094 mr0 &= ~MR0_SWFRX;
4095 portp->stats.rxxoff++;
4096 stl_sc26198wait(portp);
4097 stl_sc26198setreg(portp, MR0, mr0);
4098 }
4099 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004100 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004101 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102}
4103
4104/*****************************************************************************/
4105
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004106static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107{
4108 unsigned long flags;
4109
Jiri Slabya0564e12006-12-08 02:38:37 -08004110 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
Jiri Slaby615e4a72006-12-08 02:38:38 -08004112 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 return;
4114
Alan Coxb65b5b52006-06-27 02:54:05 -07004115 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116 BRDENABLE(portp->brdnr, portp->pagenr);
4117 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4118 stl_sc26198setreg(portp, SCCR, portp->crenable);
4119 BRDDISABLE(portp->brdnr);
4120 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004121 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122}
4123
4124/*****************************************************************************/
4125
4126/*
4127 * Return the current state of data flow on this port. This is only
4128 * really interresting when determining if data has fully completed
4129 * transmission or not... The sc26198 interrupt scheme cannot
4130 * determine when all data has actually drained, so we need to
4131 * check the port statusy register to be sure.
4132 */
4133
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004134static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135{
4136 unsigned long flags;
4137 unsigned char sr;
4138
Jiri Slabya0564e12006-12-08 02:38:37 -08004139 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Jiri Slaby615e4a72006-12-08 02:38:38 -08004141 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004142 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004144 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Alan Coxb65b5b52006-06-27 02:54:05 -07004146 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 BRDENABLE(portp->brdnr, portp->pagenr);
4148 sr = stl_sc26198getreg(portp, SR);
4149 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004150 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Jesper Juhl014c2542006-01-15 02:37:08 +01004152 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153}
4154
4155/*****************************************************************************/
4156
4157/*
4158 * Delay for a small amount of time, to give the sc26198 a chance
4159 * to process a command...
4160 */
4161
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004162static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163{
4164 int i;
4165
Jiri Slabya0564e12006-12-08 02:38:37 -08004166 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Jiri Slaby615e4a72006-12-08 02:38:38 -08004168 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 return;
4170
Jiri Slabyc62429d2006-12-08 02:39:14 -08004171 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 stl_sc26198getglobreg(portp, TSTR);
4173}
4174
4175/*****************************************************************************/
4176
4177/*
4178 * If we are TX flow controlled and in IXANY mode then we may
4179 * need to unflow control here. We gotta do this because of the
4180 * automatic flow control modes of the sc26198.
4181 */
4182
Jiri Slaby60be4812006-12-08 02:38:40 -08004183static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184{
4185 unsigned char mr0;
4186
4187 mr0 = stl_sc26198getreg(portp, MR0);
4188 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4189 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4190 stl_sc26198wait(portp);
4191 stl_sc26198setreg(portp, MR0, mr0);
4192 clear_bit(ASYI_TXFLOWED, &portp->istate);
4193}
4194
4195/*****************************************************************************/
4196
4197/*
4198 * Interrupt service routine for sc26198 panels.
4199 */
4200
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004201static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004203 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 unsigned int iack;
4205
Alan Coxb65b5b52006-06-27 02:54:05 -07004206 spin_lock(&brd_lock);
4207
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208/*
4209 * Work around bug in sc26198 chip... Cannot have A6 address
4210 * line of UART high, else iack will be returned as 0.
4211 */
4212 outb(0, (iobase + 1));
4213
4214 iack = inb(iobase + XP_IACK);
4215 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4216
4217 if (iack & IVR_RXDATA)
4218 stl_sc26198rxisr(portp, iack);
4219 else if (iack & IVR_TXDATA)
4220 stl_sc26198txisr(portp);
4221 else
4222 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004223
4224 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225}
4226
4227/*****************************************************************************/
4228
4229/*
4230 * Transmit interrupt handler. This has gotta be fast! Handling TX
4231 * chars is pretty simple, stuff as many as possible from the TX buffer
4232 * into the sc26198 FIFO.
4233 * In practice it is possible that interrupts are enabled but that the
4234 * port has been hung up. Need to handle not having any TX buffer here,
4235 * this is done by using the side effect that head and tail will also
4236 * be NULL if the buffer has been freed.
4237 */
4238
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004239static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240{
Alan Coxd18a7502008-10-13 10:40:07 +01004241 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 unsigned int ioaddr;
4243 unsigned char mr0;
4244 int len, stlen;
4245 char *head, *tail;
4246
Jiri Slabya0564e12006-12-08 02:38:37 -08004247 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248
4249 ioaddr = portp->ioaddr;
4250 head = portp->tx.head;
4251 tail = portp->tx.tail;
4252 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4253 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4254 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4255 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004256 tty = tty_port_tty_get(&portp->port);
4257 if (tty) {
4258 tty_wakeup(tty);
4259 tty_kref_put(tty);
4260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 }
4262
4263 if (len == 0) {
4264 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4265 mr0 = inb(ioaddr + XP_DATA);
4266 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4267 portp->imr &= ~IR_TXRDY;
4268 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4269 outb(portp->imr, (ioaddr + XP_DATA));
4270 clear_bit(ASYI_TXBUSY, &portp->istate);
4271 } else {
4272 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4273 outb(mr0, (ioaddr + XP_DATA));
4274 }
4275 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004276 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004278 stlen = min_t(unsigned int, len,
4279 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 outb(GTXFIFO, (ioaddr + XP_ADDR));
4281 outsb((ioaddr + XP_DATA), tail, stlen);
4282 len -= stlen;
4283 tail += stlen;
4284 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4285 tail = portp->tx.buf;
4286 if (len > 0) {
4287 outsb((ioaddr + XP_DATA), tail, len);
4288 tail += len;
4289 }
4290 portp->tx.tail = tail;
4291 }
4292}
4293
4294/*****************************************************************************/
4295
4296/*
4297 * Receive character interrupt handler. Determine if we have good chars
4298 * or bad chars and then process appropriately. Good chars are easy
4299 * just shove the lot into the RX buffer and set all status byte to 0.
4300 * If a bad RX char then process as required. This routine needs to be
4301 * fast! In practice it is possible that we get an interrupt on a port
4302 * that is closed. This can happen on hangups - since they completely
4303 * shutdown a port not in user context. Need to handle this case.
4304 */
4305
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004306static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307{
4308 struct tty_struct *tty;
4309 unsigned int len, buflen, ioaddr;
4310
Jiri Slabya0564e12006-12-08 02:38:37 -08004311 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Alan Coxd18a7502008-10-13 10:40:07 +01004313 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 ioaddr = portp->ioaddr;
4315 outb(GIBCR, (ioaddr + XP_ADDR));
4316 len = inb(ioaddr + XP_DATA) + 1;
4317
4318 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004319 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004320 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 outb(GRXFIFO, (ioaddr + XP_ADDR));
4322 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4323 portp->stats.rxlost += len;
4324 portp->stats.rxtotal += len;
4325 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004326 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004328 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004330 tty_prepare_flip_string(tty, &ptr, len);
4331 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 tty_schedule_flip(tty);
4333 portp->stats.rxtotal += len;
4334 }
4335 }
4336 } else {
4337 stl_sc26198rxbadchars(portp);
4338 }
4339
4340/*
4341 * If we are TX flow controlled and in IXANY mode then we may need
4342 * to unflow control here. We gotta do this because of the automatic
4343 * flow control modes of the sc26198.
4344 */
4345 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004346 if ((tty != NULL) &&
4347 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348 (tty->termios->c_iflag & IXANY)) {
4349 stl_sc26198txunflow(portp, tty);
4350 }
4351 }
Alan Coxd18a7502008-10-13 10:40:07 +01004352 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353}
4354
4355/*****************************************************************************/
4356
4357/*
4358 * Process an RX bad character.
4359 */
4360
Jiri Slaby60be4812006-12-08 02:38:40 -08004361static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362{
4363 struct tty_struct *tty;
4364 unsigned int ioaddr;
4365
Alan Coxd18a7502008-10-13 10:40:07 +01004366 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 ioaddr = portp->ioaddr;
4368
4369 if (status & SR_RXPARITY)
4370 portp->stats.rxparity++;
4371 if (status & SR_RXFRAMING)
4372 portp->stats.rxframing++;
4373 if (status & SR_RXOVERRUN)
4374 portp->stats.rxoverrun++;
4375 if (status & SR_RXBREAK)
4376 portp->stats.rxbreaks++;
4377
Jiri Slaby615e4a72006-12-08 02:38:38 -08004378 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379 ((portp->rxignoremsk & status) == 0)) {
4380 if (portp->rxmarkmsk & status) {
4381 if (status & SR_RXBREAK) {
4382 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004383 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 do_SAK(tty);
4385 BRDENABLE(portp->brdnr, portp->pagenr);
4386 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004387 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004389 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004391 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004393 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004395 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Alan Cox33f0f882006-01-09 20:54:13 -08004398 tty_insert_flip_char(tty, ch, status);
4399 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
4401 if (status == 0)
4402 portp->stats.rxtotal++;
4403 }
Alan Coxd18a7502008-10-13 10:40:07 +01004404 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405}
4406
4407/*****************************************************************************/
4408
4409/*
4410 * Process all characters in the RX FIFO of the UART. Check all char
4411 * status bytes as well, and process as required. We need to check
4412 * all bytes in the FIFO, in case some more enter the FIFO while we
4413 * are here. To get the exact character error type we need to switch
4414 * into CHAR error mode (that is why we need to make sure we empty
4415 * the FIFO).
4416 */
4417
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004418static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419{
4420 unsigned char status, mr1;
4421 char ch;
4422
4423/*
4424 * To get the precise error type for each character we must switch
4425 * back into CHAR error mode.
4426 */
4427 mr1 = stl_sc26198getreg(portp, MR1);
4428 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4429
4430 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4431 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4432 ch = stl_sc26198getreg(portp, RXFIFO);
4433 stl_sc26198rxbadch(portp, status, ch);
4434 }
4435
4436/*
4437 * To get correct interrupt class we must switch back into BLOCK
4438 * error mode.
4439 */
4440 stl_sc26198setreg(portp, MR1, mr1);
4441}
4442
4443/*****************************************************************************/
4444
4445/*
4446 * Other interrupt handler. This includes modem signals, flow
4447 * control actions, etc. Most stuff is left to off-level interrupt
4448 * processing time.
4449 */
4450
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004451static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452{
4453 unsigned char cir, ipr, xisr;
4454
Jiri Slabya0564e12006-12-08 02:38:37 -08004455 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
4457 cir = stl_sc26198getglobreg(portp, CIR);
4458
4459 switch (cir & CIR_SUBTYPEMASK) {
4460 case CIR_SUBCOS:
4461 ipr = stl_sc26198getreg(portp, IPR);
4462 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004463 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464 portp->stats.modem++;
4465 }
4466 break;
4467 case CIR_SUBXONXOFF:
4468 xisr = stl_sc26198getreg(portp, XISR);
4469 if (xisr & XISR_RXXONGOT) {
4470 set_bit(ASYI_TXFLOWED, &portp->istate);
4471 portp->stats.txxoff++;
4472 }
4473 if (xisr & XISR_RXXOFFGOT) {
4474 clear_bit(ASYI_TXFLOWED, &portp->istate);
4475 portp->stats.txxon++;
4476 }
4477 break;
4478 case CIR_SUBBREAK:
4479 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4480 stl_sc26198rxbadchars(portp);
4481 break;
4482 default:
4483 break;
4484 }
4485}
4486
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004487static void stl_free_isabrds(void)
4488{
4489 struct stlbrd *brdp;
4490 unsigned int i;
4491
4492 for (i = 0; i < stl_nrbrds; i++) {
4493 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4494 continue;
4495
4496 free_irq(brdp->irq, brdp);
4497
4498 stl_cleanup_panels(brdp);
4499
4500 release_region(brdp->ioaddr1, brdp->iosize1);
4501 if (brdp->iosize2 > 0)
4502 release_region(brdp->ioaddr2, brdp->iosize2);
4503
4504 kfree(brdp);
4505 stl_brds[i] = NULL;
4506 }
4507}
4508
Jiri Slaby23b85a12006-12-08 02:38:40 -08004509/*
4510 * Loadable module initialization stuff.
4511 */
4512static int __init stallion_module_init(void)
4513{
Jiri Slaby843b5682006-12-08 02:39:12 -08004514 struct stlbrd *brdp;
4515 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004516 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004517 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004518
4519 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4520
4521 spin_lock_init(&stallion_lock);
4522 spin_lock_init(&brd_lock);
4523
Jiri Slabye4151092007-06-08 13:46:52 -07004524 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4525 if (!stl_serial) {
4526 retval = -ENOMEM;
4527 goto err;
4528 }
4529
4530 stl_serial->owner = THIS_MODULE;
4531 stl_serial->driver_name = stl_drvname;
4532 stl_serial->name = "ttyE";
4533 stl_serial->major = STL_SERIALMAJOR;
4534 stl_serial->minor_start = 0;
4535 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4536 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4537 stl_serial->init_termios = stl_deftermios;
4538 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4539 tty_set_operations(stl_serial, &stl_ops);
4540
4541 retval = tty_register_driver(stl_serial);
4542 if (retval) {
4543 printk("STALLION: failed to register serial driver\n");
4544 goto err_frtty;
4545 }
4546
Jiri Slaby843b5682006-12-08 02:39:12 -08004547/*
4548 * Find any dynamically supported boards. That is via module load
4549 * line options.
4550 */
4551 for (i = stl_nrbrds; i < stl_nargs; i++) {
4552 memset(&conf, 0, sizeof(conf));
4553 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4554 continue;
4555 if ((brdp = stl_allocbrd()) == NULL)
4556 continue;
4557 brdp->brdnr = i;
4558 brdp->brdtype = conf.brdtype;
4559 brdp->ioaddr1 = conf.ioaddr1;
4560 brdp->ioaddr2 = conf.ioaddr2;
4561 brdp->irq = conf.irq;
4562 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004563 stl_brds[brdp->brdnr] = brdp;
4564 if (stl_brdinit(brdp)) {
4565 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004566 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004567 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004568 for (j = 0; j < brdp->nrports; j++)
4569 tty_register_device(stl_serial,
4570 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004571 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004572 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004573 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004574
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004575 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004576 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004577 if (retval && stl_nrbrds == 0) {
4578 printk(KERN_ERR "STALLION: can't register pci driver\n");
4579 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004580 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004581
4582/*
4583 * Set up a character driver for per board stuff. This is mainly used
4584 * to do stats ioctls on the ports.
4585 */
4586 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4587 printk("STALLION: failed to register serial board device\n");
4588
4589 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004590 if (IS_ERR(stallion_class))
4591 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004592 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004593 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4594 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004595
Jiri Slaby23b85a12006-12-08 02:38:40 -08004596 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004597err_unrtty:
4598 tty_unregister_driver(stl_serial);
4599err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004600 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004601err:
4602 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004603}
4604
4605static void __exit stallion_module_exit(void)
4606{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004607 struct stlbrd *brdp;
4608 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004609
4610 pr_debug("cleanup_module()\n");
4611
4612 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4613 stl_drvversion);
4614
4615/*
4616 * Free up all allocated resources used by the ports. This includes
4617 * memory and interrupts. As part of this process we will also do
4618 * a hangup on every open port - to try to flush out any processes
4619 * hanging onto ports.
4620 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004621 for (i = 0; i < stl_nrbrds; i++) {
4622 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4623 continue;
4624 for (j = 0; j < brdp->nrports; j++)
4625 tty_unregister_device(stl_serial,
4626 brdp->brdnr * STL_MAXPORTS + j);
4627 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004628
Jiri Slaby23b85a12006-12-08 02:38:40 -08004629 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004630 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004631 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004632 class_destroy(stallion_class);
4633
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004634 pci_unregister_driver(&stl_pcidriver);
4635
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004636 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004637
4638 tty_unregister_driver(stl_serial);
4639 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004640}
4641
4642module_init(stallion_module_init);
4643module_exit(stallion_module_exit);
4644
4645MODULE_AUTHOR("Greg Ungerer");
4646MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4647MODULE_LICENSE("GPL");