blob: 4bef6ab83622f5e0e71ed6532a7f4cca12397a1c [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,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200611 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612};
613
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800614static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800616static void stl_cd_change(struct stlport *portp)
617{
618 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100619 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800620
Alan Coxd18a7502008-10-13 10:40:07 +0100621 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800622 return;
623
624 portp->sigs = stl_getsignals(portp);
625
626 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100627 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800628
629 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100630 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100631 tty_hangup(tty);
632 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800633}
634
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 * Check for any arguments passed in on the module load command line.
637 */
638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639/*****************************************************************************/
640
641/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 * Parse the supplied argument string, into the board conf struct.
643 */
644
Jiri Slaby40e82652006-12-08 02:38:41 -0800645static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
647 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800648 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Jiri Slabya0564e12006-12-08 02:38:37 -0800650 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Jiri Slaby615e4a72006-12-08 02:38:38 -0800652 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100653 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Jiri Slabyc62429d2006-12-08 02:39:14 -0800655 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800656 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Jiri Slabyc62429d2006-12-08 02:39:14 -0800658 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
660 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800661
Tobias Klauserfe971072006-01-09 20:54:02 -0800662 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800664 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 }
666
667 confp->brdtype = stl_brdstr[i].type;
668
669 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800670 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800671 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 i++;
673 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800674 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800675 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 i++;
677 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800678 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800679 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100680 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681}
682
683/*****************************************************************************/
684
685/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 * Allocate a new board structure. Fill out the basic info in it.
687 */
688
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800689static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800691 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800693 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800694 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700695 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800696 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800697 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100701 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702}
703
704/*****************************************************************************/
705
Alan Cox047e9652009-11-30 13:17:03 +0000706static int stl_activate(struct tty_port *port, struct tty_struct *tty)
707{
708 struct stlport *portp = container_of(port, struct stlport, port);
709 if (!portp->tx.buf) {
710 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
711 if (!portp->tx.buf)
712 return -ENOMEM;
713 portp->tx.head = portp->tx.buf;
714 portp->tx.tail = portp->tx.buf;
715 }
716 stl_setport(portp, tty->termios);
717 portp->sigs = stl_getsignals(portp);
718 stl_setsignals(portp, 1, 1);
719 stl_enablerxtx(portp, 1, 1);
720 stl_startrxtx(portp, 1, 0);
721 return 0;
722}
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724static int stl_open(struct tty_struct *tty, struct file *filp)
725{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800726 struct stlport *portp;
727 struct stlbrd *brdp;
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 Coxa2d1e352010-04-23 16:01:18 +0100757
758 tty->driver_data = portp;
Alan Cox047e9652009-11-30 13:17:03 +0000759 return tty_port_open(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761}
762
763/*****************************************************************************/
764
Alan Cox31f35932009-01-02 13:45:05 +0000765static int stl_carrier_raised(struct tty_port *port)
766{
767 struct stlport *portp = container_of(port, struct stlport, port);
768 return (portp->sigs & TIOCM_CD) ? 1 : 0;
769}
770
Alan Coxfcc8ac12009-06-11 12:24:17 +0100771static void stl_dtr_rts(struct tty_port *port, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
Alan Cox4350f3f2009-01-02 13:46:24 +0000773 struct stlport *portp = container_of(port, struct stlport, port);
774 /* Takes brd_lock internally */
Alan Coxfcc8ac12009-06-11 12:24:17 +0100775 stl_setsignals(portp, on, on);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776}
777
778/*****************************************************************************/
779
Jiri Slaby96b066b2006-12-08 02:38:42 -0800780static void stl_flushbuffer(struct tty_struct *tty)
781{
782 struct stlport *portp;
783
784 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
785
Jiri Slaby96b066b2006-12-08 02:38:42 -0800786 portp = tty->driver_data;
787 if (portp == NULL)
788 return;
789
790 stl_flush(portp);
791 tty_wakeup(tty);
792}
793
794/*****************************************************************************/
795
796static void stl_waituntilsent(struct tty_struct *tty, int timeout)
797{
798 struct stlport *portp;
799 unsigned long tend;
800
801 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
802
Jiri Slaby96b066b2006-12-08 02:38:42 -0800803 portp = tty->driver_data;
804 if (portp == NULL)
805 return;
806
807 if (timeout == 0)
808 timeout = HZ;
809 tend = jiffies + timeout;
810
811 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 }
818}
819
820/*****************************************************************************/
821
Alan Cox047e9652009-11-30 13:17:03 +0000822static void stl_shutdown(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823{
Alan Cox047e9652009-11-30 13:17:03 +0000824 struct stlport *portp = container_of(port, struct stlport, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 stl_disableintrs(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 stl_enablerxtx(portp, 0, 0);
Alan Cox047e9652009-11-30 13:17:03 +0000827 stl_flush(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800829 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800831 portp->tx.buf = NULL;
832 portp->tx.head = NULL;
833 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 }
Alan Cox047e9652009-11-30 13:17:03 +0000835}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Alan Cox047e9652009-11-30 13:17:03 +0000837static void stl_close(struct tty_struct *tty, struct file *filp)
838{
839 struct stlport*portp;
840 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
841
842 portp = tty->driver_data;
Alan Coxa2d1e352010-04-23 16:01:18 +0100843 if(portp == NULL)
844 return;
Alan Cox047e9652009-11-30 13:17:03 +0000845 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));
Alan Coxb4eda9c2010-06-01 22:52:41 +02001031
1032 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 sio.line = portp->portnr;
1034 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001035 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 sio.baud_base = portp->baud_base;
1037 sio.close_delay = portp->close_delay;
1038 sio.closing_wait = portp->closing_wait;
1039 sio.custom_divisor = portp->custom_divisor;
1040 sio.hub6 = 0;
1041 if (portp->uartp == &stl_cd1400uart) {
1042 sio.type = PORT_CIRRUS;
1043 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1044 } else {
1045 sio.type = PORT_UNKNOWN;
1046 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1047 }
1048
1049 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001050 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 sio.irq = brdp->irq;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001052 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1055}
1056
1057/*****************************************************************************/
1058
1059/*
1060 * Set port according to the serial struct info.
1061 * At this point we do not do any auto-configure stuff, so we will
1062 * just quietly ignore any requests to change irq, etc.
1063 */
1064
Alan Coxd18a7502008-10-13 10:40:07 +01001065static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066{
Alan Coxd18a7502008-10-13 10:40:07 +01001067 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 struct serial_struct sio;
1069
Jiri Slabya0564e12006-12-08 02:38:37 -08001070 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1073 return -EFAULT;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001074 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 if (!capable(CAP_SYS_ADMIN)) {
1076 if ((sio.baud_base != portp->baud_base) ||
1077 (sio.close_delay != portp->close_delay) ||
1078 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxb4eda9c2010-06-01 22:52:41 +02001079 (portp->port.flags & ~ASYNC_USR_MASK))) {
1080 mutex_unlock(&portp->port.mutex);
Jesper Juhl014c2542006-01-15 02:37:08 +01001081 return -EPERM;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 }
1084
Alan Coxf8ae4762008-07-16 21:56:37 +01001085 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 (sio.flags & ASYNC_USR_MASK);
1087 portp->baud_base = sio.baud_base;
1088 portp->close_delay = sio.close_delay;
1089 portp->closing_wait = sio.closing_wait;
1090 portp->custom_divisor = sio.custom_divisor;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001091 mutex_unlock(&portp->port.mutex);
Alan Coxd18a7502008-10-13 10:40:07 +01001092 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001093 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
1096/*****************************************************************************/
1097
1098static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1099{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001100 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001103 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001104 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001106 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108 return stl_getsignals(portp);
1109}
1110
1111static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1112 unsigned int set, unsigned int clear)
1113{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001114 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 int rts = -1, dtr = -1;
1116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001118 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001119 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001121 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
1123 if (set & TIOCM_RTS)
1124 rts = 1;
1125 if (set & TIOCM_DTR)
1126 dtr = 1;
1127 if (clear & TIOCM_RTS)
1128 rts = 0;
1129 if (clear & TIOCM_DTR)
1130 dtr = 0;
1131
1132 stl_setsignals(portp, dtr, rts);
1133 return 0;
1134}
1135
1136static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1137{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001138 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 int rc;
1140 void __user *argp = (void __user *)arg;
1141
Jiri Slabya0564e12006-12-08 02:38:37 -08001142 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1143 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001146 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001147 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
1149 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001150 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001152 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 rc = 0;
1155
1156 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 case TIOCGSERIAL:
1158 rc = stl_getserial(portp, argp);
1159 break;
1160 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001161 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 break;
1163 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001164 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 break;
1166 case COM_CLRPORTSTATS:
1167 rc = stl_clrportstats(portp, argp);
1168 break;
1169 case TIOCSERCONFIG:
1170 case TIOCSERGWILD:
1171 case TIOCSERSWILD:
1172 case TIOCSERGETLSR:
1173 case TIOCSERGSTRUCT:
1174 case TIOCSERGETMULTI:
1175 case TIOCSERSETMULTI:
1176 default:
1177 rc = -ENOIOCTLCMD;
1178 break;
1179 }
Jesper Juhl014c2542006-01-15 02:37:08 +01001180 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181}
1182
1183/*****************************************************************************/
1184
Jiri Slaby96b066b2006-12-08 02:38:42 -08001185/*
1186 * Start the transmitter again. Just turn TX interrupts back on.
1187 */
1188
1189static void stl_start(struct tty_struct *tty)
1190{
1191 struct stlport *portp;
1192
1193 pr_debug("stl_start(tty=%p)\n", tty);
1194
Jiri Slaby96b066b2006-12-08 02:38:42 -08001195 portp = tty->driver_data;
1196 if (portp == NULL)
1197 return;
1198 stl_startrxtx(portp, -1, 1);
1199}
1200
1201/*****************************************************************************/
1202
Alan Cox606d0992006-12-08 02:38:45 -08001203static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001205 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001206 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Jiri Slabya0564e12006-12-08 02:38:37 -08001208 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001211 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return;
1213
1214 tiosp = tty->termios;
1215 if ((tiosp->c_cflag == old->c_cflag) &&
1216 (tiosp->c_iflag == old->c_iflag))
1217 return;
1218
1219 stl_setport(portp, tiosp);
1220 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1221 -1);
1222 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1223 tty->hw_stopped = 0;
1224 stl_start(tty);
1225 }
1226 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001227 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228}
1229
1230/*****************************************************************************/
1231
1232/*
1233 * Attempt to flow control who ever is sending us data. Based on termios
1234 * settings use software or/and hardware flow control.
1235 */
1236
1237static void stl_throttle(struct tty_struct *tty)
1238{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001239 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Jiri Slabya0564e12006-12-08 02:38:37 -08001241 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001244 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 return;
1246 stl_flowctrl(portp, 0);
1247}
1248
1249/*****************************************************************************/
1250
1251/*
1252 * Unflow control the device sending us data...
1253 */
1254
1255static void stl_unthrottle(struct tty_struct *tty)
1256{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001257 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Jiri Slabya0564e12006-12-08 02:38:37 -08001259 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001262 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 return;
1264 stl_flowctrl(portp, 1);
1265}
1266
1267/*****************************************************************************/
1268
1269/*
1270 * Stop the transmitter. Basically to do this we will just turn TX
1271 * interrupts off.
1272 */
1273
1274static void stl_stop(struct tty_struct *tty)
1275{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001276 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Jiri Slabya0564e12006-12-08 02:38:37 -08001278 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001281 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return;
1283 stl_startrxtx(portp, -1, 0);
1284}
1285
1286/*****************************************************************************/
1287
1288/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 * Hangup this port. This is pretty much like closing the port, only
1290 * a little more brutal. No waiting for data to drain. Shutdown the
1291 * port and maybe drop signals.
1292 */
1293
1294static void stl_hangup(struct tty_struct *tty)
1295{
Alan Cox047e9652009-11-30 13:17:03 +00001296 struct stlport *portp = tty->driver_data;
Jiri Slabya0564e12006-12-08 02:38:37 -08001297 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Jiri Slaby615e4a72006-12-08 02:38:38 -08001299 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 return;
Alan Cox047e9652009-11-30 13:17:03 +00001301 tty_port_hangup(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302}
1303
1304/*****************************************************************************/
1305
David Howells4a561222008-07-22 11:18:43 +01001306static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001308 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Jiri Slabya0564e12006-12-08 02:38:37 -08001310 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001313 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001314 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
1316 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001317 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318}
1319
1320/*****************************************************************************/
1321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322static void stl_sendxchar(struct tty_struct *tty, char ch)
1323{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001324 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Jiri Slabya0564e12006-12-08 02:38:37 -08001326 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001329 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 return;
1331
1332 if (ch == STOP_CHAR(tty))
1333 stl_sendflow(portp, 0);
1334 else if (ch == START_CHAR(tty))
1335 stl_sendflow(portp, 1);
1336 else
1337 stl_putchar(tty, ch);
1338}
1339
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001340static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001342 int sigs;
1343 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001345 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1347 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1348
1349 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001350 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001352 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001354 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001356 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001359 sep = ' ';
1360 if (sigs & TIOCM_RTS) {
1361 seq_printf(m, "%c%s", sep, "RTS");
1362 sep = '|';
1363 }
1364 if (sigs & TIOCM_CTS) {
1365 seq_printf(m, "%c%s", sep, "CTS");
1366 sep = '|';
1367 }
1368 if (sigs & TIOCM_DTR) {
1369 seq_printf(m, "%c%s", sep, "DTR");
1370 sep = '|';
1371 }
1372 if (sigs & TIOCM_CD) {
1373 seq_printf(m, "%c%s", sep, "DCD");
1374 sep = '|';
1375 }
1376 if (sigs & TIOCM_DSR) {
1377 seq_printf(m, "%c%s", sep, "DSR");
1378 sep = '|';
1379 }
1380 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381}
1382
1383/*****************************************************************************/
1384
1385/*
1386 * Port info, read from the /proc file system.
1387 */
1388
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001389static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001391 struct stlbrd *brdp;
1392 struct stlpanel *panelp;
1393 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001394 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001395 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001399 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401/*
1402 * We scan through for each board, panel and port. The offset is
1403 * calculated on the fly, and irrelevant ports are skipped.
1404 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001405 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001407 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 continue;
1409 if (brdp->state == 0)
1410 continue;
1411
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001413 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001415 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 continue;
1417
Jiri Slabyc62429d2006-12-08 02:39:14 -08001418 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 totalport++) {
1420 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001421 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001423 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425 }
1426 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001427 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428}
1429
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001430static int stl_proc_open(struct inode *inode, struct file *file)
1431{
1432 return single_open(file, stl_proc_show, NULL);
1433}
1434
1435static const struct file_operations stl_proc_fops = {
1436 .owner = THIS_MODULE,
1437 .open = stl_proc_open,
1438 .read = seq_read,
1439 .llseek = seq_lseek,
1440 .release = single_release,
1441};
1442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443/*****************************************************************************/
1444
1445/*
1446 * All board interrupts are vectored through here first. This code then
1447 * calls off to the approrpriate board interrupt handlers.
1448 */
1449
David Howells7d12e782006-10-05 14:55:46 +01001450static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001452 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Jeff Garzika6f97b22007-10-31 05:20:49 -04001454 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
1456 return IRQ_RETVAL((* brdp->isr)(brdp));
1457}
1458
1459/*****************************************************************************/
1460
1461/*
1462 * Interrupt service routine for EasyIO board types.
1463 */
1464
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001467 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 unsigned int iobase;
1469 int handled = 0;
1470
Alan Coxb65b5b52006-06-27 02:54:05 -07001471 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 panelp = brdp->panels[0];
1473 iobase = panelp->iobase;
1474 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1475 handled = 1;
1476 (* panelp->isr)(panelp, iobase);
1477 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001478 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return handled;
1480}
1481
1482/*****************************************************************************/
1483
1484/*
1485 * Interrupt service routine for ECH-AT board types.
1486 */
1487
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001488static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001490 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001491 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 int handled = 0;
1493
1494 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1495
1496 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1497 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001498 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 ioaddr = brdp->bnkstataddr[bnknr];
1500 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1501 panelp = brdp->bnk2panel[bnknr];
1502 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1503 }
1504 }
1505 }
1506
1507 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1508
1509 return handled;
1510}
1511
1512/*****************************************************************************/
1513
1514/*
1515 * Interrupt service routine for ECH-MCA board types.
1516 */
1517
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001518static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001520 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001521 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 int handled = 0;
1523
1524 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1525 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001526 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 ioaddr = brdp->bnkstataddr[bnknr];
1528 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1529 panelp = brdp->bnk2panel[bnknr];
1530 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1531 }
1532 }
1533 }
1534 return handled;
1535}
1536
1537/*****************************************************************************/
1538
1539/*
1540 * Interrupt service routine for ECH-PCI board types.
1541 */
1542
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001543static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001545 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001546 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 int handled = 0;
1548
1549 while (1) {
1550 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001551 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1553 ioaddr = brdp->bnkstataddr[bnknr];
1554 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1555 panelp = brdp->bnk2panel[bnknr];
1556 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1557 recheck++;
1558 handled = 1;
1559 }
1560 }
1561 if (! recheck)
1562 break;
1563 }
1564 return handled;
1565}
1566
1567/*****************************************************************************/
1568
1569/*
1570 * Interrupt service routine for ECH-8/64-PCI board types.
1571 */
1572
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001573static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001575 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001576 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 int handled = 0;
1578
1579 while (inb(brdp->ioctrl) & 0x1) {
1580 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001581 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 ioaddr = brdp->bnkstataddr[bnknr];
1583 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1584 panelp = brdp->bnk2panel[bnknr];
1585 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1586 }
1587 }
1588 }
1589
1590 return handled;
1591}
1592
1593/*****************************************************************************/
1594
1595/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 * Initialize all the ports on a panel.
1597 */
1598
Jiri Slaby705c1862006-12-08 02:39:11 -08001599static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001601 struct stlport *portp;
1602 unsigned int i;
1603 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
Jiri Slabya0564e12006-12-08 02:38:37 -08001605 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
1607 chipmask = stl_panelinit(brdp, panelp);
1608
1609/*
1610 * All UART's are initialized (if found!). Now go through and setup
1611 * each ports data structures.
1612 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001613 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001614 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001615 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001617 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 break;
1619 }
Alan Coxd18a7502008-10-13 10:40:07 +01001620 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001621 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 portp->magic = STL_PORTMAGIC;
1623 portp->portnr = i;
1624 portp->brdnr = panelp->brdnr;
1625 portp->panelnr = panelp->panelnr;
1626 portp->uartp = panelp->uartp;
1627 portp->clk = brdp->clk;
1628 portp->baud_base = STL_BAUDBASE;
1629 portp->close_delay = STL_CLOSEDELAY;
1630 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001631 init_waitqueue_head(&portp->port.open_wait);
1632 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 portp->stats.brd = portp->brdnr;
1634 portp->stats.panel = portp->panelnr;
1635 portp->stats.port = portp->portnr;
1636 panelp->ports[i] = portp;
1637 stl_portinit(brdp, panelp, portp);
1638 }
1639
Jiri Slabyc62429d2006-12-08 02:39:14 -08001640 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641}
1642
Jiri Slaby3b85b342006-12-08 02:39:10 -08001643static void stl_cleanup_panels(struct stlbrd *brdp)
1644{
1645 struct stlpanel *panelp;
1646 struct stlport *portp;
1647 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001648 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001649
1650 for (j = 0; j < STL_MAXPANELS; j++) {
1651 panelp = brdp->panels[j];
1652 if (panelp == NULL)
1653 continue;
1654 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1655 portp = panelp->ports[k];
1656 if (portp == NULL)
1657 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001658 tty = tty_port_tty_get(&portp->port);
1659 if (tty != NULL) {
1660 stl_hangup(tty);
1661 tty_kref_put(tty);
1662 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001663 kfree(portp->tx.buf);
1664 kfree(portp);
1665 }
1666 kfree(panelp);
1667 }
1668}
1669
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670/*****************************************************************************/
1671
1672/*
1673 * Try to find and initialize an EasyIO board.
1674 */
1675
Jiri Slaby705c1862006-12-08 02:39:11 -08001676static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001678 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 unsigned int status;
1680 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001681 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
Jiri Slabya0564e12006-12-08 02:38:37 -08001683 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
1685 brdp->ioctrl = brdp->ioaddr1 + 1;
1686 brdp->iostatus = brdp->ioaddr1 + 2;
1687
1688 status = inb(brdp->iostatus);
1689 if ((status & EIO_IDBITMASK) == EIO_MK3)
1690 brdp->ioctrl++;
1691
1692/*
1693 * Handle board specific stuff now. The real difference is PCI
1694 * or not PCI.
1695 */
1696 if (brdp->brdtype == BRD_EASYIOPCI) {
1697 brdp->iosize1 = 0x80;
1698 brdp->iosize2 = 0x80;
1699 name = "serial(EIO-PCI)";
1700 outb(0x41, (brdp->ioaddr2 + 0x4c));
1701 } else {
1702 brdp->iosize1 = 8;
1703 name = "serial(EIO)";
1704 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1705 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1706 printk("STALLION: invalid irq=%d for brd=%d\n",
1707 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001708 retval = -EINVAL;
1709 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 }
1711 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1712 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1713 brdp->ioctrl);
1714 }
1715
Jiri Slaby3b85b342006-12-08 02:39:10 -08001716 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1718 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1719 "%x conflicts with another device\n", brdp->brdnr,
1720 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001721 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 }
1723
1724 if (brdp->iosize2 > 0)
1725 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1726 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1727 "address %x conflicts with another device\n",
1728 brdp->brdnr, brdp->ioaddr2);
1729 printk(KERN_WARNING "STALLION: Warning, also "
1730 "releasing board %d I/O address %x \n",
1731 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001732 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 }
1734
1735/*
1736 * Everything looks OK, so let's go ahead and probe for the hardware.
1737 */
1738 brdp->clk = CD1400_CLK;
1739 brdp->isr = stl_eiointr;
1740
Jiri Slaby3b85b342006-12-08 02:39:10 -08001741 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 switch (status & EIO_IDBITMASK) {
1743 case EIO_8PORTM:
1744 brdp->clk = CD1400_CLK8M;
1745 /* fall thru */
1746 case EIO_8PORTRS:
1747 case EIO_8PORTDI:
1748 brdp->nrports = 8;
1749 break;
1750 case EIO_4PORTRS:
1751 brdp->nrports = 4;
1752 break;
1753 case EIO_MK3:
1754 switch (status & EIO_BRDMASK) {
1755 case ID_BRD4:
1756 brdp->nrports = 4;
1757 break;
1758 case ID_BRD8:
1759 brdp->nrports = 8;
1760 break;
1761 case ID_BRD16:
1762 brdp->nrports = 16;
1763 break;
1764 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001765 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 }
1767 break;
1768 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001769 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 }
1771
1772/*
1773 * We have verified that the board is actually present, so now we
1774 * can complete the setup.
1775 */
1776
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001777 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001778 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001780 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001781 retval = -ENOMEM;
1782 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
1785 panelp->magic = STL_PANELMAGIC;
1786 panelp->brdnr = brdp->brdnr;
1787 panelp->panelnr = 0;
1788 panelp->nrports = brdp->nrports;
1789 panelp->iobase = brdp->ioaddr1;
1790 panelp->hwid = status;
1791 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001792 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 panelp->isr = stl_sc26198intr;
1794 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001795 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 panelp->isr = stl_cd1400eiointr;
1797 }
1798
1799 brdp->panels[0] = panelp;
1800 brdp->nrpanels = 1;
1801 brdp->state |= BRD_FOUND;
1802 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001803 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 printk("STALLION: failed to register interrupt "
1805 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001806 retval = -ENODEV;
1807 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001809
1810 return 0;
1811err_fr:
1812 stl_cleanup_panels(brdp);
1813err_rel2:
1814 if (brdp->iosize2 > 0)
1815 release_region(brdp->ioaddr2, brdp->iosize2);
1816err_rel1:
1817 release_region(brdp->ioaddr1, brdp->iosize1);
1818err:
1819 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820}
1821
1822/*****************************************************************************/
1823
1824/*
1825 * Try to find an ECH board and initialize it. This code is capable of
1826 * dealing with all types of ECH board.
1827 */
1828
Jiri Slaby705c1862006-12-08 02:39:11 -08001829static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001831 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001832 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1833 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 char *name;
1835
Jiri Slabya0564e12006-12-08 02:38:37 -08001836 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
1838 status = 0;
1839 conflict = 0;
1840
1841/*
1842 * Set up the initial board register contents for boards. This varies a
1843 * bit between the different board types. So we need to handle each
1844 * separately. Also do a check that the supplied IRQ is good.
1845 */
1846 switch (brdp->brdtype) {
1847
1848 case BRD_ECH:
1849 brdp->isr = stl_echatintr;
1850 brdp->ioctrl = brdp->ioaddr1 + 1;
1851 brdp->iostatus = brdp->ioaddr1 + 1;
1852 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001853 if ((status & ECH_IDBITMASK) != ECH_ID) {
1854 retval = -ENODEV;
1855 goto err;
1856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1858 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1859 printk("STALLION: invalid irq=%d for brd=%d\n",
1860 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001861 retval = -EINVAL;
1862 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 }
1864 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1865 status |= (stl_vecmap[brdp->irq] << 1);
1866 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1867 brdp->ioctrlval = ECH_INTENABLE |
1868 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001869 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1871 brdp->iosize1 = 2;
1872 brdp->iosize2 = 32;
1873 name = "serial(EC8/32)";
1874 outb(status, brdp->ioaddr1);
1875 break;
1876
1877 case BRD_ECHMC:
1878 brdp->isr = stl_echmcaintr;
1879 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1880 brdp->iostatus = brdp->ioctrl;
1881 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001882 if ((status & ECH_IDBITMASK) != ECH_ID) {
1883 retval = -ENODEV;
1884 goto err;
1885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1887 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1888 printk("STALLION: invalid irq=%d for brd=%d\n",
1889 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001890 retval = -EINVAL;
1891 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 }
1893 outb(ECHMC_BRDRESET, brdp->ioctrl);
1894 outb(ECHMC_INTENABLE, brdp->ioctrl);
1895 brdp->iosize1 = 64;
1896 name = "serial(EC8/32-MC)";
1897 break;
1898
1899 case BRD_ECHPCI:
1900 brdp->isr = stl_echpciintr;
1901 brdp->ioctrl = brdp->ioaddr1 + 2;
1902 brdp->iosize1 = 4;
1903 brdp->iosize2 = 8;
1904 name = "serial(EC8/32-PCI)";
1905 break;
1906
1907 case BRD_ECH64PCI:
1908 brdp->isr = stl_echpci64intr;
1909 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1910 outb(0x43, (brdp->ioaddr1 + 0x4c));
1911 brdp->iosize1 = 0x80;
1912 brdp->iosize2 = 0x80;
1913 name = "serial(EC8/64-PCI)";
1914 break;
1915
1916 default:
1917 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001918 retval = -EINVAL;
1919 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 }
1921
1922/*
1923 * Check boards for possible IO address conflicts and return fail status
1924 * if an IO conflict found.
1925 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001926 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1928 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1929 "%x conflicts with another device\n", brdp->brdnr,
1930 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001931 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
1933
1934 if (brdp->iosize2 > 0)
1935 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1936 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1937 "address %x conflicts with another device\n",
1938 brdp->brdnr, brdp->ioaddr2);
1939 printk(KERN_WARNING "STALLION: Warning, also "
1940 "releasing board %d I/O address %x \n",
1941 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001942 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 }
1944
1945/*
1946 * Scan through the secondary io address space looking for panels.
1947 * As we find'em allocate and initialize panel structures for each.
1948 */
1949 brdp->clk = CD1400_CLK;
1950 brdp->hwid = status;
1951
1952 ioaddr = brdp->ioaddr2;
1953 banknr = 0;
1954 panelnr = 0;
1955 nxtid = 0;
1956
Jiri Slabyc62429d2006-12-08 02:39:14 -08001957 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 if (brdp->brdtype == BRD_ECHPCI) {
1959 outb(nxtid, brdp->ioctrl);
1960 ioaddr = brdp->ioaddr2;
1961 }
1962 status = inb(ioaddr + ECH_PNLSTATUS);
1963 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07001964 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001965 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001966 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001968 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07001969 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001970 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 panelp->magic = STL_PANELMAGIC;
1973 panelp->brdnr = brdp->brdnr;
1974 panelp->panelnr = panelnr;
1975 panelp->iobase = ioaddr;
1976 panelp->pagenr = nxtid;
1977 panelp->hwid = status;
1978 brdp->bnk2panel[banknr] = panelp;
1979 brdp->bnkpageaddr[banknr] = nxtid;
1980 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
1981
1982 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001983 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 panelp->isr = stl_sc26198intr;
1985 if (status & ECH_PNL16PORT) {
1986 panelp->nrports = 16;
1987 brdp->bnk2panel[banknr] = panelp;
1988 brdp->bnkpageaddr[banknr] = nxtid;
1989 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
1990 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001991 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001994 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 panelp->isr = stl_cd1400echintr;
1996 if (status & ECH_PNL16PORT) {
1997 panelp->nrports = 16;
1998 panelp->ackmask = 0x80;
1999 if (brdp->brdtype != BRD_ECHPCI)
2000 ioaddr += EREG_BANKSIZE;
2001 brdp->bnk2panel[banknr] = panelp;
2002 brdp->bnkpageaddr[banknr] = ++nxtid;
2003 brdp->bnkstataddr[banknr++] = ioaddr +
2004 ECH_PNLSTATUS;
2005 } else {
2006 panelp->nrports = 8;
2007 panelp->ackmask = 0xc0;
2008 }
2009 }
2010
2011 nxtid++;
2012 ioaddr += EREG_BANKSIZE;
2013 brdp->nrports += panelp->nrports;
2014 brdp->panels[panelnr++] = panelp;
2015 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002016 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2017 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002018 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021
2022 brdp->nrpanels = panelnr;
2023 brdp->nrbnks = banknr;
2024 if (brdp->brdtype == BRD_ECH)
2025 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2026
2027 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002028 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 printk("STALLION: failed to register interrupt "
2030 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002031 retval = -ENODEV;
2032 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 }
2034
Jiri Slaby3b85b342006-12-08 02:39:10 -08002035 return 0;
2036err_fr:
2037 stl_cleanup_panels(brdp);
2038 if (brdp->iosize2 > 0)
2039 release_region(brdp->ioaddr2, brdp->iosize2);
2040err_rel1:
2041 release_region(brdp->ioaddr1, brdp->iosize1);
2042err:
2043 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044}
2045
2046/*****************************************************************************/
2047
2048/*
2049 * Initialize and configure the specified board.
2050 * Scan through all the boards in the configuration and see what we
2051 * can find. Handle EIO and the ECH boards a little differently here
2052 * since the initial search and setup is very different.
2053 */
2054
Jiri Slaby705c1862006-12-08 02:39:11 -08002055static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002057 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
Jiri Slabya0564e12006-12-08 02:38:37 -08002059 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
2061 switch (brdp->brdtype) {
2062 case BRD_EASYIO:
2063 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002064 retval = stl_initeio(brdp);
2065 if (retval)
2066 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 break;
2068 case BRD_ECH:
2069 case BRD_ECHMC:
2070 case BRD_ECHPCI:
2071 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002072 retval = stl_initech(brdp);
2073 if (retval)
2074 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 break;
2076 default:
2077 printk("STALLION: board=%d is unknown board type=%d\n",
2078 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002079 retval = -ENODEV;
2080 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 }
2082
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 if ((brdp->state & BRD_FOUND) == 0) {
2084 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2085 stl_brdnames[brdp->brdtype], brdp->brdnr,
2086 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002087 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 }
2089
Jiri Slabyc62429d2006-12-08 02:39:14 -08002090 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002091 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 stl_initports(brdp, brdp->panels[i]);
2093
2094 printk("STALLION: %s found, board=%d io=%x irq=%d "
2095 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2096 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2097 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002098
2099 return 0;
2100err_free:
2101 free_irq(brdp->irq, brdp);
2102
2103 stl_cleanup_panels(brdp);
2104
2105 release_region(brdp->ioaddr1, brdp->iosize1);
2106 if (brdp->iosize2 > 0)
2107 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002108err:
2109 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110}
2111
2112/*****************************************************************************/
2113
2114/*
2115 * Find the next available board number that is free.
2116 */
2117
Jiri Slaby705c1862006-12-08 02:39:11 -08002118static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002120 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
Jiri Slabyc62429d2006-12-08 02:39:14 -08002122 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002123 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 if (i >= stl_nrbrds)
2125 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002126 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002128
2129 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130}
2131
2132/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133/*
2134 * We have a Stallion board. Allocate a board structure and
2135 * initialize it. Read its IO and IRQ resources from PCI
2136 * configuration space.
2137 */
2138
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002139static int __devinit stl_pciprobe(struct pci_dev *pdev,
2140 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002142 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002143 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002144 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002146 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002147 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002148
Jiri Slaby3b85b342006-12-08 02:39:10 -08002149 retval = pci_enable_device(pdev);
2150 if (retval)
2151 goto err;
2152 brdp = stl_allocbrd();
2153 if (brdp == NULL) {
2154 retval = -ENOMEM;
2155 goto err;
2156 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002157 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002158 brdnr = stl_getbrdnr();
2159 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002160 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002162 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002163 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002164 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002166 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002167 stl_brds[brdp->brdnr] = brdp;
2168 mutex_unlock(&stl_brdslock);
2169
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002171 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
2173/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 * We have all resources from the board, so let's setup the actual
2175 * board structure now.
2176 */
2177 switch (brdtype) {
2178 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002179 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2180 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 break;
2182 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002183 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2184 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 break;
2186 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002187 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2188 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189 break;
2190 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002191 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 break;
2193 }
2194
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002195 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002196 retval = stl_brdinit(brdp);
2197 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002198 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002200 pci_set_drvdata(pdev, brdp);
2201
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002202 for (i = 0; i < brdp->nrports; i++)
2203 tty_register_device(stl_serial,
2204 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2205
Jiri Slaby3b85b342006-12-08 02:39:10 -08002206 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002207err_null:
2208 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002209err_fr:
2210 kfree(brdp);
2211err:
2212 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213}
2214
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002215static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002217 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002218 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002220 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002222 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002224 release_region(brdp->ioaddr1, brdp->iosize1);
2225 if (brdp->iosize2 > 0)
2226 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002228 for (i = 0; i < brdp->nrports; i++)
2229 tty_unregister_device(stl_serial,
2230 brdp->brdnr * STL_MAXPORTS + i);
2231
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002232 stl_brds[brdp->brdnr] = NULL;
2233 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234}
2235
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002236static struct pci_driver stl_pcidriver = {
2237 .name = "stallion",
2238 .id_table = stl_pcibrds,
2239 .probe = stl_pciprobe,
2240 .remove = __devexit_p(stl_pciremove)
2241};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243/*****************************************************************************/
2244
2245/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 * Return the board stats structure to user app.
2247 */
2248
2249static int stl_getbrdstats(combrd_t __user *bp)
2250{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002251 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002252 struct stlbrd *brdp;
2253 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002254 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
2256 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2257 return -EFAULT;
2258 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002259 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002261 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002262 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
2264 memset(&stl_brdstats, 0, sizeof(combrd_t));
2265 stl_brdstats.brd = brdp->brdnr;
2266 stl_brdstats.type = brdp->brdtype;
2267 stl_brdstats.hwid = brdp->hwid;
2268 stl_brdstats.state = brdp->state;
2269 stl_brdstats.ioaddr = brdp->ioaddr1;
2270 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2271 stl_brdstats.irq = brdp->irq;
2272 stl_brdstats.nrpanels = brdp->nrpanels;
2273 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002274 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 panelp = brdp->panels[i];
2276 stl_brdstats.panels[i].panel = i;
2277 stl_brdstats.panels[i].hwid = panelp->hwid;
2278 stl_brdstats.panels[i].nrports = panelp->nrports;
2279 }
2280
2281 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2282}
2283
2284/*****************************************************************************/
2285
2286/*
2287 * Resolve the referenced port number into a port struct pointer.
2288 */
2289
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002290static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002292 struct stlbrd *brdp;
2293 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
Jiri Slabyc62429d2006-12-08 02:39:14 -08002295 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2296 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002298 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002299 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002300 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002301 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002303 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002304 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002305 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002306 return NULL;
2307 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308}
2309
2310/*****************************************************************************/
2311
2312/*
2313 * Return the port stats structure to user app. A NULL port struct
2314 * pointer passed in means that we need to find out from the app
2315 * what port to get stats for (used through board control device).
2316 */
2317
Alan Coxd18a7502008-10-13 10:40:07 +01002318static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002320 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 unsigned char *head, *tail;
2322 unsigned long flags;
2323
2324 if (!portp) {
2325 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2326 return -EFAULT;
2327 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2328 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002329 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002330 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 }
2332
Alan Coxb4eda9c2010-06-01 22:52:41 +02002333 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002335 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 portp->stats.hwid = portp->hwid;
2337
2338 portp->stats.ttystate = 0;
2339 portp->stats.cflags = 0;
2340 portp->stats.iflags = 0;
2341 portp->stats.oflags = 0;
2342 portp->stats.lflags = 0;
2343 portp->stats.rxbuffered = 0;
2344
Alan Coxb65b5b52006-06-27 02:54:05 -07002345 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002346 if (tty != NULL && portp->port.tty == tty) {
2347 portp->stats.ttystate = tty->flags;
2348 /* No longer available as a statistic */
2349 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2350 if (tty->termios != NULL) {
2351 portp->stats.cflags = tty->termios->c_cflag;
2352 portp->stats.iflags = tty->termios->c_iflag;
2353 portp->stats.oflags = tty->termios->c_oflag;
2354 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 }
Alan Coxd18a7502008-10-13 10:40:07 +01002356 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002357 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 head = portp->tx.head;
2360 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002361 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2362 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364 portp->stats.signals = (unsigned long) stl_getsignals(portp);
Alan Coxb4eda9c2010-06-01 22:52:41 +02002365 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
2367 return copy_to_user(cp, &portp->stats,
2368 sizeof(comstats_t)) ? -EFAULT : 0;
2369}
2370
2371/*****************************************************************************/
2372
2373/*
2374 * Clear the port stats structure. We also return it zeroed out...
2375 */
2376
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002377static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002379 comstats_t stl_comstats;
2380
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 if (!portp) {
2382 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2383 return -EFAULT;
2384 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2385 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002386 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002387 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 }
2389
Alan Coxb4eda9c2010-06-01 22:52:41 +02002390 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 memset(&portp->stats, 0, sizeof(comstats_t));
2392 portp->stats.brd = portp->brdnr;
2393 portp->stats.panel = portp->panelnr;
2394 portp->stats.port = portp->portnr;
Alan Coxb4eda9c2010-06-01 22:52:41 +02002395 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 return copy_to_user(cp, &portp->stats,
2397 sizeof(comstats_t)) ? -EFAULT : 0;
2398}
2399
2400/*****************************************************************************/
2401
2402/*
2403 * Return the entire driver ports structure to a user app.
2404 */
2405
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002406static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002408 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002409 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002411 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 return -EFAULT;
2413 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2414 stl_dummyport.portnr);
2415 if (!portp)
2416 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002417 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418}
2419
2420/*****************************************************************************/
2421
2422/*
2423 * Return the entire driver board structure to a user app.
2424 */
2425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002426static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002428 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002429 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002431 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002433 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 return -ENODEV;
2435 brdp = stl_brds[stl_dummybrd.brdnr];
2436 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002437 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002438 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439}
2440
2441/*****************************************************************************/
2442
2443/*
2444 * The "staliomem" device is also required to do some special operations
2445 * on the board and/or ports. In this driver it is mostly used for stats
2446 * collection.
2447 */
2448
Alan Cox894cb912009-10-13 16:34:15 +01002449static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450{
2451 int brdnr, rc;
2452 void __user *argp = (void __user *)arg;
2453
Alan Cox894cb912009-10-13 16:34:15 +01002454 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Alan Cox894cb912009-10-13 16:34:15 +01002456 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002458 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 rc = 0;
2460
2461 switch (cmd) {
2462 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002463 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 break;
2465 case COM_CLRPORTSTATS:
2466 rc = stl_clrportstats(NULL, argp);
2467 break;
2468 case COM_GETBRDSTATS:
2469 rc = stl_getbrdstats(argp);
2470 break;
2471 case COM_READPORT:
2472 rc = stl_getportstruct(argp);
2473 break;
2474 case COM_READBOARD:
2475 rc = stl_getbrdstruct(argp);
2476 break;
2477 default:
2478 rc = -ENOIOCTLCMD;
2479 break;
2480 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002481 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482}
2483
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002484static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 .open = stl_open,
2486 .close = stl_close,
2487 .write = stl_write,
2488 .put_char = stl_putchar,
2489 .flush_chars = stl_flushchars,
2490 .write_room = stl_writeroom,
2491 .chars_in_buffer = stl_charsinbuffer,
2492 .ioctl = stl_ioctl,
2493 .set_termios = stl_settermios,
2494 .throttle = stl_throttle,
2495 .unthrottle = stl_unthrottle,
2496 .stop = stl_stop,
2497 .start = stl_start,
2498 .hangup = stl_hangup,
2499 .flush_buffer = stl_flushbuffer,
2500 .break_ctl = stl_breakctl,
2501 .wait_until_sent = stl_waituntilsent,
2502 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 .tiocmget = stl_tiocmget,
2504 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002505 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506};
2507
Alan Cox31f35932009-01-02 13:45:05 +00002508static const struct tty_port_operations stl_port_ops = {
2509 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002510 .dtr_rts = stl_dtr_rts,
Alan Cox047e9652009-11-30 13:17:03 +00002511 .activate = stl_activate,
2512 .shutdown = stl_shutdown,
Alan Cox31f35932009-01-02 13:45:05 +00002513};
2514
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516/* CD1400 HARDWARE FUNCTIONS */
2517/*****************************************************************************/
2518
2519/*
2520 * These functions get/set/update the registers of the cd1400 UARTs.
2521 * Access to the cd1400 registers is via an address/data io port pair.
2522 * (Maybe should make this inline...)
2523 */
2524
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002525static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526{
2527 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002528 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529}
2530
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002531static void stl_cd1400setreg(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 outb(value, portp->ioaddr + EREG_DATA);
2535}
2536
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002537static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002539 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 if (inb(portp->ioaddr + EREG_DATA) != value) {
2541 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002542 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002544 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545}
2546
2547/*****************************************************************************/
2548
2549/*
2550 * Inbitialize the UARTs in a panel. We don't care what sort of board
2551 * these ports are on - since the port io registers are almost
2552 * identical when dealing with ports.
2553 */
2554
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002555static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556{
2557 unsigned int gfrcr;
2558 int chipmask, i, j;
2559 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002560 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Jiri Slabya0564e12006-12-08 02:38:37 -08002562 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Alan Coxb65b5b52006-06-27 02:54:05 -07002564 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 BRDENABLE(panelp->brdnr, panelp->pagenr);
2566
2567/*
2568 * Check that each chip is present and started up OK.
2569 */
2570 chipmask = 0;
2571 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002572 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 if (brdp->brdtype == BRD_ECHPCI) {
2574 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2575 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002576 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 uartaddr = (i & 0x01) ? 0x080 : 0;
2579 outb((GFRCR + uartaddr), ioaddr);
2580 outb(0, (ioaddr + EREG_DATA));
2581 outb((CCR + uartaddr), ioaddr);
2582 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2583 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2584 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002585 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2587 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2590 printk("STALLION: cd1400 not responding, "
2591 "brd=%d panel=%d chip=%d\n",
2592 panelp->brdnr, panelp->panelnr, i);
2593 continue;
2594 }
2595 chipmask |= (0x1 << i);
2596 outb((PPR + uartaddr), ioaddr);
2597 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2598 }
2599
2600 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002601 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002602 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603}
2604
2605/*****************************************************************************/
2606
2607/*
2608 * Initialize hardware specific port registers.
2609 */
2610
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002611static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612{
Alan Coxb65b5b52006-06-27 02:54:05 -07002613 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002614 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2615 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Jiri Slaby615e4a72006-12-08 02:38:38 -08002617 if ((brdp == NULL) || (panelp == NULL) ||
2618 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 return;
2620
Alan Coxb65b5b52006-06-27 02:54:05 -07002621 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2623 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2624 portp->uartaddr = (portp->portnr & 0x04) << 5;
2625 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2626
2627 BRDENABLE(portp->brdnr, portp->pagenr);
2628 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2629 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2630 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2631 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002632 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633}
2634
2635/*****************************************************************************/
2636
2637/*
2638 * Wait for the command register to be ready. We will poll this,
2639 * since it won't usually take too long to be ready.
2640 */
2641
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002642static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643{
2644 int i;
2645
Jiri Slabyc62429d2006-12-08 02:39:14 -08002646 for (i = 0; i < CCR_MAXWAIT; i++)
2647 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649
2650 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2651 portp->portnr, portp->panelnr, portp->brdnr);
2652}
2653
2654/*****************************************************************************/
2655
2656/*
2657 * Set up the cd1400 registers for a port based on the termios port
2658 * settings.
2659 */
2660
Alan Cox606d0992006-12-08 02:38:45 -08002661static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002663 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 unsigned long flags;
2665 unsigned int clkdiv, baudrate;
2666 unsigned char cor1, cor2, cor3;
2667 unsigned char cor4, cor5, ccr;
2668 unsigned char srer, sreron, sreroff;
2669 unsigned char mcor1, mcor2, rtpr;
2670 unsigned char clk, div;
2671
2672 cor1 = 0;
2673 cor2 = 0;
2674 cor3 = 0;
2675 cor4 = 0;
2676 cor5 = 0;
2677 ccr = 0;
2678 rtpr = 0;
2679 clk = 0;
2680 div = 0;
2681 mcor1 = 0;
2682 mcor2 = 0;
2683 sreron = 0;
2684 sreroff = 0;
2685
2686 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002687 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 return;
2689
2690/*
2691 * Set up the RX char ignore mask with those RX error types we
2692 * can ignore. We can get the cd1400 to help us out a little here,
2693 * it will ignore parity errors and breaks for us.
2694 */
2695 portp->rxignoremsk = 0;
2696 if (tiosp->c_iflag & IGNPAR) {
2697 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2698 cor1 |= COR1_PARIGNORE;
2699 }
2700 if (tiosp->c_iflag & IGNBRK) {
2701 portp->rxignoremsk |= ST_BREAK;
2702 cor4 |= COR4_IGNBRK;
2703 }
2704
2705 portp->rxmarkmsk = ST_OVERRUN;
2706 if (tiosp->c_iflag & (INPCK | PARMRK))
2707 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2708 if (tiosp->c_iflag & BRKINT)
2709 portp->rxmarkmsk |= ST_BREAK;
2710
2711/*
2712 * Go through the char size, parity and stop bits and set all the
2713 * option register appropriately.
2714 */
2715 switch (tiosp->c_cflag & CSIZE) {
2716 case CS5:
2717 cor1 |= COR1_CHL5;
2718 break;
2719 case CS6:
2720 cor1 |= COR1_CHL6;
2721 break;
2722 case CS7:
2723 cor1 |= COR1_CHL7;
2724 break;
2725 default:
2726 cor1 |= COR1_CHL8;
2727 break;
2728 }
2729
2730 if (tiosp->c_cflag & CSTOPB)
2731 cor1 |= COR1_STOP2;
2732 else
2733 cor1 |= COR1_STOP1;
2734
2735 if (tiosp->c_cflag & PARENB) {
2736 if (tiosp->c_cflag & PARODD)
2737 cor1 |= (COR1_PARENB | COR1_PARODD);
2738 else
2739 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2740 } else {
2741 cor1 |= COR1_PARNONE;
2742 }
2743
2744/*
2745 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2746 * space for hardware flow control and the like. This should be set to
2747 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2748 * really be based on VTIME.
2749 */
2750 cor3 |= FIFO_RXTHRESHOLD;
2751 rtpr = 2;
2752
2753/*
2754 * Calculate the baud rate timers. For now we will just assume that
2755 * the input and output baud are the same. Could have used a baud
2756 * table here, but this way we can generate virtually any baud rate
2757 * we like!
2758 */
2759 baudrate = tiosp->c_cflag & CBAUD;
2760 if (baudrate & CBAUDEX) {
2761 baudrate &= ~CBAUDEX;
2762 if ((baudrate < 1) || (baudrate > 4))
2763 tiosp->c_cflag &= ~CBAUDEX;
2764 else
2765 baudrate += 15;
2766 }
2767 baudrate = stl_baudrates[baudrate];
2768 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002769 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002771 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002773 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002775 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002777 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 baudrate = (portp->baud_base / portp->custom_divisor);
2779 }
2780 if (baudrate > STL_CD1400MAXBAUD)
2781 baudrate = STL_CD1400MAXBAUD;
2782
2783 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002784 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2785 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 if (clkdiv < 0x100)
2787 break;
2788 }
2789 div = (unsigned char) clkdiv;
2790 }
2791
2792/*
2793 * Check what form of modem signaling is required and set it up.
2794 */
2795 if ((tiosp->c_cflag & CLOCAL) == 0) {
2796 mcor1 |= MCOR1_DCD;
2797 mcor2 |= MCOR2_DCD;
2798 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002799 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002800 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002801 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
2803/*
2804 * Setup cd1400 enhanced modes if we can. In particular we want to
2805 * handle as much of the flow control as possible automatically. As
2806 * well as saving a few CPU cycles it will also greatly improve flow
2807 * control reliability.
2808 */
2809 if (tiosp->c_iflag & IXON) {
2810 cor2 |= COR2_TXIBE;
2811 cor3 |= COR3_SCD12;
2812 if (tiosp->c_iflag & IXANY)
2813 cor2 |= COR2_IXM;
2814 }
2815
2816 if (tiosp->c_cflag & CRTSCTS) {
2817 cor2 |= COR2_CTSAE;
2818 mcor1 |= FIFO_RTSTHRESHOLD;
2819 }
2820
2821/*
2822 * All cd1400 register values calculated so go through and set
2823 * them all up.
2824 */
2825
Jiri Slabya0564e12006-12-08 02:38:37 -08002826 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002828 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002830 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002832 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2833 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2835 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836
Alan Coxb65b5b52006-06-27 02:54:05 -07002837 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 BRDENABLE(portp->brdnr, portp->pagenr);
2839 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2840 srer = stl_cd1400getreg(portp, SRER);
2841 stl_cd1400setreg(portp, SRER, 0);
2842 if (stl_cd1400updatereg(portp, COR1, cor1))
2843 ccr = 1;
2844 if (stl_cd1400updatereg(portp, COR2, cor2))
2845 ccr = 1;
2846 if (stl_cd1400updatereg(portp, COR3, cor3))
2847 ccr = 1;
2848 if (ccr) {
2849 stl_cd1400ccrwait(portp);
2850 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2851 }
2852 stl_cd1400setreg(portp, COR4, cor4);
2853 stl_cd1400setreg(portp, COR5, cor5);
2854 stl_cd1400setreg(portp, MCOR1, mcor1);
2855 stl_cd1400setreg(portp, MCOR2, mcor2);
2856 if (baudrate > 0) {
2857 stl_cd1400setreg(portp, TCOR, clk);
2858 stl_cd1400setreg(portp, TBPR, div);
2859 stl_cd1400setreg(portp, RCOR, clk);
2860 stl_cd1400setreg(portp, RBPR, div);
2861 }
2862 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2863 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2864 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2865 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2866 stl_cd1400setreg(portp, RTPR, rtpr);
2867 mcor1 = stl_cd1400getreg(portp, MSVR1);
2868 if (mcor1 & MSVR1_DCD)
2869 portp->sigs |= TIOCM_CD;
2870 else
2871 portp->sigs &= ~TIOCM_CD;
2872 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2873 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002874 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875}
2876
2877/*****************************************************************************/
2878
2879/*
2880 * Set the state of the DTR and RTS signals.
2881 */
2882
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002883static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884{
2885 unsigned char msvr1, msvr2;
2886 unsigned long flags;
2887
Jiri Slabya0564e12006-12-08 02:38:37 -08002888 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2889 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890
2891 msvr1 = 0;
2892 msvr2 = 0;
2893 if (dtr > 0)
2894 msvr1 = MSVR1_DTR;
2895 if (rts > 0)
2896 msvr2 = MSVR2_RTS;
2897
Alan Coxb65b5b52006-06-27 02:54:05 -07002898 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 BRDENABLE(portp->brdnr, portp->pagenr);
2900 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2901 if (rts >= 0)
2902 stl_cd1400setreg(portp, MSVR2, msvr2);
2903 if (dtr >= 0)
2904 stl_cd1400setreg(portp, MSVR1, msvr1);
2905 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002906 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907}
2908
2909/*****************************************************************************/
2910
2911/*
2912 * Return the state of the signals.
2913 */
2914
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002915static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916{
2917 unsigned char msvr1, msvr2;
2918 unsigned long flags;
2919 int sigs;
2920
Jiri Slabya0564e12006-12-08 02:38:37 -08002921 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
Alan Coxb65b5b52006-06-27 02:54:05 -07002923 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 BRDENABLE(portp->brdnr, portp->pagenr);
2925 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2926 msvr1 = stl_cd1400getreg(portp, MSVR1);
2927 msvr2 = stl_cd1400getreg(portp, MSVR2);
2928 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002929 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 sigs = 0;
2932 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2933 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2934 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2935 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2936#if 0
2937 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2938 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2939#else
2940 sigs |= TIOCM_DSR;
2941#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002942 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943}
2944
2945/*****************************************************************************/
2946
2947/*
2948 * Enable/Disable the Transmitter and/or Receiver.
2949 */
2950
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002951static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952{
2953 unsigned char ccr;
2954 unsigned long flags;
2955
Jiri Slabya0564e12006-12-08 02:38:37 -08002956 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2957
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 ccr = 0;
2959
2960 if (tx == 0)
2961 ccr |= CCR_TXDISABLE;
2962 else if (tx > 0)
2963 ccr |= CCR_TXENABLE;
2964 if (rx == 0)
2965 ccr |= CCR_RXDISABLE;
2966 else if (rx > 0)
2967 ccr |= CCR_RXENABLE;
2968
Alan Coxb65b5b52006-06-27 02:54:05 -07002969 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970 BRDENABLE(portp->brdnr, portp->pagenr);
2971 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2972 stl_cd1400ccrwait(portp);
2973 stl_cd1400setreg(portp, CCR, ccr);
2974 stl_cd1400ccrwait(portp);
2975 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002976 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977}
2978
2979/*****************************************************************************/
2980
2981/*
2982 * Start/stop the Transmitter and/or Receiver.
2983 */
2984
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002985static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986{
2987 unsigned char sreron, sreroff;
2988 unsigned long flags;
2989
Jiri Slabya0564e12006-12-08 02:38:37 -08002990 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 sreron = 0;
2993 sreroff = 0;
2994 if (tx == 0)
2995 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
2996 else if (tx == 1)
2997 sreron |= SRER_TXDATA;
2998 else if (tx >= 2)
2999 sreron |= SRER_TXEMPTY;
3000 if (rx == 0)
3001 sreroff |= SRER_RXDATA;
3002 else if (rx > 0)
3003 sreron |= SRER_RXDATA;
3004
Alan Coxb65b5b52006-06-27 02:54:05 -07003005 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 BRDENABLE(portp->brdnr, portp->pagenr);
3007 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3008 stl_cd1400setreg(portp, SRER,
3009 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3010 BRDDISABLE(portp->brdnr);
3011 if (tx > 0)
3012 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003013 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014}
3015
3016/*****************************************************************************/
3017
3018/*
3019 * Disable all interrupts from this port.
3020 */
3021
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003022static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023{
3024 unsigned long flags;
3025
Jiri Slabya0564e12006-12-08 02:38:37 -08003026 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3027
Alan Coxb65b5b52006-06-27 02:54:05 -07003028 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 BRDENABLE(portp->brdnr, portp->pagenr);
3030 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3031 stl_cd1400setreg(portp, SRER, 0);
3032 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003033 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034}
3035
3036/*****************************************************************************/
3037
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003038static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039{
3040 unsigned long flags;
3041
Jiri Slabya0564e12006-12-08 02:38:37 -08003042 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043
Alan Coxb65b5b52006-06-27 02:54:05 -07003044 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 BRDENABLE(portp->brdnr, portp->pagenr);
3046 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3047 stl_cd1400setreg(portp, SRER,
3048 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3049 SRER_TXEMPTY));
3050 BRDDISABLE(portp->brdnr);
3051 portp->brklen = len;
3052 if (len == 1)
3053 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003054 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055}
3056
3057/*****************************************************************************/
3058
3059/*
3060 * Take flow control actions...
3061 */
3062
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003063static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064{
3065 struct tty_struct *tty;
3066 unsigned long flags;
3067
Jiri Slabya0564e12006-12-08 02:38:37 -08003068 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Jiri Slaby615e4a72006-12-08 02:38:38 -08003070 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003072 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003073 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 return;
3075
Alan Coxb65b5b52006-06-27 02:54:05 -07003076 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 BRDENABLE(portp->brdnr, portp->pagenr);
3078 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3079
3080 if (state) {
3081 if (tty->termios->c_iflag & IXOFF) {
3082 stl_cd1400ccrwait(portp);
3083 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3084 portp->stats.rxxon++;
3085 stl_cd1400ccrwait(portp);
3086 }
3087/*
3088 * Question: should we return RTS to what it was before? It may
3089 * have been set by an ioctl... Suppose not, since if you have
3090 * hardware flow control set then it is pretty silly to go and
3091 * set the RTS line by hand.
3092 */
3093 if (tty->termios->c_cflag & CRTSCTS) {
3094 stl_cd1400setreg(portp, MCOR1,
3095 (stl_cd1400getreg(portp, MCOR1) |
3096 FIFO_RTSTHRESHOLD));
3097 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3098 portp->stats.rxrtson++;
3099 }
3100 } else {
3101 if (tty->termios->c_iflag & IXOFF) {
3102 stl_cd1400ccrwait(portp);
3103 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3104 portp->stats.rxxoff++;
3105 stl_cd1400ccrwait(portp);
3106 }
3107 if (tty->termios->c_cflag & CRTSCTS) {
3108 stl_cd1400setreg(portp, MCOR1,
3109 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3110 stl_cd1400setreg(portp, MSVR2, 0);
3111 portp->stats.rxrtsoff++;
3112 }
3113 }
3114
3115 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003116 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003117 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118}
3119
3120/*****************************************************************************/
3121
3122/*
3123 * Send a flow control character...
3124 */
3125
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003126static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127{
3128 struct tty_struct *tty;
3129 unsigned long flags;
3130
Jiri Slabya0564e12006-12-08 02:38:37 -08003131 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
Jiri Slaby615e4a72006-12-08 02:38:38 -08003133 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003135 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003136 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 return;
3138
Alan Coxb65b5b52006-06-27 02:54:05 -07003139 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 BRDENABLE(portp->brdnr, portp->pagenr);
3141 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3142 if (state) {
3143 stl_cd1400ccrwait(portp);
3144 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3145 portp->stats.rxxon++;
3146 stl_cd1400ccrwait(portp);
3147 } else {
3148 stl_cd1400ccrwait(portp);
3149 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3150 portp->stats.rxxoff++;
3151 stl_cd1400ccrwait(portp);
3152 }
3153 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003154 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003155 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156}
3157
3158/*****************************************************************************/
3159
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003160static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161{
3162 unsigned long flags;
3163
Jiri Slabya0564e12006-12-08 02:38:37 -08003164 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165
Jiri Slaby615e4a72006-12-08 02:38:38 -08003166 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 return;
3168
Alan Coxb65b5b52006-06-27 02:54:05 -07003169 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 BRDENABLE(portp->brdnr, portp->pagenr);
3171 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3172 stl_cd1400ccrwait(portp);
3173 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3174 stl_cd1400ccrwait(portp);
3175 portp->tx.tail = portp->tx.head;
3176 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003177 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178}
3179
3180/*****************************************************************************/
3181
3182/*
3183 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02003184 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 * transmission or not... This is easy for the cd1400, it accurately
3186 * maintains the busy port flag.
3187 */
3188
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003189static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190{
Jiri Slabya0564e12006-12-08 02:38:37 -08003191 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
Jiri Slaby615e4a72006-12-08 02:38:38 -08003193 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003194 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195
Jesper Juhl014c2542006-01-15 02:37:08 +01003196 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197}
3198
3199/*****************************************************************************/
3200
3201/*
3202 * Interrupt service routine for cd1400 EasyIO boards.
3203 */
3204
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003205static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206{
3207 unsigned char svrtype;
3208
Jiri Slabya0564e12006-12-08 02:38:37 -08003209 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Alan Coxb65b5b52006-06-27 02:54:05 -07003211 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 outb(SVRR, iobase);
3213 svrtype = inb(iobase + EREG_DATA);
3214 if (panelp->nrports > 4) {
3215 outb((SVRR + 0x80), iobase);
3216 svrtype |= inb(iobase + EREG_DATA);
3217 }
3218
3219 if (svrtype & SVRR_RX)
3220 stl_cd1400rxisr(panelp, iobase);
3221 else if (svrtype & SVRR_TX)
3222 stl_cd1400txisr(panelp, iobase);
3223 else if (svrtype & SVRR_MDM)
3224 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003225
3226 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
3229/*****************************************************************************/
3230
3231/*
3232 * Interrupt service routine for cd1400 panels.
3233 */
3234
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003235static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236{
3237 unsigned char svrtype;
3238
Jiri Slabya0564e12006-12-08 02:38:37 -08003239 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240
3241 outb(SVRR, iobase);
3242 svrtype = inb(iobase + EREG_DATA);
3243 outb((SVRR + 0x80), iobase);
3244 svrtype |= inb(iobase + EREG_DATA);
3245 if (svrtype & SVRR_RX)
3246 stl_cd1400rxisr(panelp, iobase);
3247 else if (svrtype & SVRR_TX)
3248 stl_cd1400txisr(panelp, iobase);
3249 else if (svrtype & SVRR_MDM)
3250 stl_cd1400mdmisr(panelp, iobase);
3251}
3252
3253
3254/*****************************************************************************/
3255
3256/*
3257 * Unfortunately we need to handle breaks in the TX data stream, since
3258 * this is the only way to generate them on the cd1400.
3259 */
3260
Jiri Slaby60be4812006-12-08 02:38:40 -08003261static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262{
3263 if (portp->brklen == 1) {
3264 outb((COR2 + portp->uartaddr), ioaddr);
3265 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3266 (ioaddr + EREG_DATA));
3267 outb((TDR + portp->uartaddr), ioaddr);
3268 outb(ETC_CMD, (ioaddr + EREG_DATA));
3269 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3270 outb((SRER + portp->uartaddr), ioaddr);
3271 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3272 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003273 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274 } else if (portp->brklen > 1) {
3275 outb((TDR + portp->uartaddr), ioaddr);
3276 outb(ETC_CMD, (ioaddr + EREG_DATA));
3277 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3278 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003279 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 } else {
3281 outb((COR2 + portp->uartaddr), ioaddr);
3282 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3283 (ioaddr + EREG_DATA));
3284 portp->brklen = 0;
3285 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003286 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287}
3288
3289/*****************************************************************************/
3290
3291/*
3292 * Transmit interrupt handler. This has gotta be fast! Handling TX
3293 * chars is pretty simple, stuff as many as possible from the TX buffer
3294 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3295 * are embedded as commands in the data stream. Oh no, had to use a goto!
3296 * This could be optimized more, will do when I get time...
3297 * In practice it is possible that interrupts are enabled but that the
3298 * port has been hung up. Need to handle not having any TX buffer here,
3299 * this is done by using the side effect that head and tail will also
3300 * be NULL if the buffer has been freed.
3301 */
3302
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003303static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003305 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 int len, stlen;
3307 char *head, *tail;
3308 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003309 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
Jiri Slabya0564e12006-12-08 02:38:37 -08003311 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
3313 ioack = inb(ioaddr + EREG_TXACK);
3314 if (((ioack & panelp->ackmask) != 0) ||
3315 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3316 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3317 return;
3318 }
3319 portp = panelp->ports[(ioack >> 3)];
3320
3321/*
3322 * Unfortunately we need to handle breaks in the data stream, since
3323 * this is the only way to generate them on the cd1400. Do it now if
3324 * a break is to be sent.
3325 */
3326 if (portp->brklen != 0)
3327 if (stl_cd1400breakisr(portp, ioaddr))
3328 goto stl_txalldone;
3329
3330 head = portp->tx.head;
3331 tail = portp->tx.tail;
3332 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3333 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3334 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3335 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003336 tty = tty_port_tty_get(&portp->port);
3337 if (tty) {
3338 tty_wakeup(tty);
3339 tty_kref_put(tty);
3340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 }
3342
3343 if (len == 0) {
3344 outb((SRER + portp->uartaddr), ioaddr);
3345 srer = inb(ioaddr + EREG_DATA);
3346 if (srer & SRER_TXDATA) {
3347 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3348 } else {
3349 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3350 clear_bit(ASYI_TXBUSY, &portp->istate);
3351 }
3352 outb(srer, (ioaddr + EREG_DATA));
3353 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003354 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003356 stlen = min_t(unsigned int, len,
3357 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 outb((TDR + portp->uartaddr), ioaddr);
3359 outsb((ioaddr + EREG_DATA), tail, stlen);
3360 len -= stlen;
3361 tail += stlen;
3362 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3363 tail = portp->tx.buf;
3364 if (len > 0) {
3365 outsb((ioaddr + EREG_DATA), tail, len);
3366 tail += len;
3367 }
3368 portp->tx.tail = tail;
3369 }
3370
3371stl_txalldone:
3372 outb((EOSRR + portp->uartaddr), ioaddr);
3373 outb(0, (ioaddr + EREG_DATA));
3374}
3375
3376/*****************************************************************************/
3377
3378/*
3379 * Receive character interrupt handler. Determine if we have good chars
3380 * or bad chars and then process appropriately. Good chars are easy
3381 * just shove the lot into the RX buffer and set all status byte to 0.
3382 * If a bad RX char then process as required. This routine needs to be
3383 * fast! In practice it is possible that we get an interrupt on a port
3384 * that is closed. This can happen on hangups - since they completely
3385 * shutdown a port not in user context. Need to handle this case.
3386 */
3387
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003388static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003390 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 struct tty_struct *tty;
3392 unsigned int ioack, len, buflen;
3393 unsigned char status;
3394 char ch;
3395
Jiri Slabya0564e12006-12-08 02:38:37 -08003396 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397
3398 ioack = inb(ioaddr + EREG_RXACK);
3399 if ((ioack & panelp->ackmask) != 0) {
3400 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3401 return;
3402 }
3403 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003404 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
3406 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3407 outb((RDCR + portp->uartaddr), ioaddr);
3408 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003409 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003410 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 outb((RDSR + portp->uartaddr), ioaddr);
3412 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3413 portp->stats.rxlost += len;
3414 portp->stats.rxtotal += len;
3415 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003416 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003418 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003420 tty_prepare_flip_string(tty, &ptr, len);
3421 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 tty_schedule_flip(tty);
3423 portp->stats.rxtotal += len;
3424 }
3425 }
3426 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3427 outb((RDSR + portp->uartaddr), ioaddr);
3428 status = inb(ioaddr + EREG_DATA);
3429 ch = inb(ioaddr + EREG_DATA);
3430 if (status & ST_PARITY)
3431 portp->stats.rxparity++;
3432 if (status & ST_FRAMING)
3433 portp->stats.rxframing++;
3434 if (status & ST_OVERRUN)
3435 portp->stats.rxoverrun++;
3436 if (status & ST_BREAK)
3437 portp->stats.rxbreaks++;
3438 if (status & ST_SCHARMASK) {
3439 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3440 portp->stats.txxon++;
3441 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3442 portp->stats.txxoff++;
3443 goto stl_rxalldone;
3444 }
Alan Cox33f0f882006-01-09 20:54:13 -08003445 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 if (portp->rxmarkmsk & status) {
3447 if (status & ST_BREAK) {
3448 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003449 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 do_SAK(tty);
3451 BRDENABLE(portp->brdnr, portp->pagenr);
3452 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003453 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003455 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003457 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003459 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003461 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003463 tty_insert_flip_char(tty, ch, status);
3464 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 }
3466 } else {
3467 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003468 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 return;
3470 }
3471
3472stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003473 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 outb((EOSRR + portp->uartaddr), ioaddr);
3475 outb(0, (ioaddr + EREG_DATA));
3476}
3477
3478/*****************************************************************************/
3479
3480/*
3481 * Modem interrupt handler. The is called when the modem signal line
3482 * (DCD) has changed state. Leave most of the work to the off-level
3483 * processing routine.
3484 */
3485
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003486static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003488 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 unsigned int ioack;
3490 unsigned char misr;
3491
Jiri Slabya0564e12006-12-08 02:38:37 -08003492 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493
3494 ioack = inb(ioaddr + EREG_MDACK);
3495 if (((ioack & panelp->ackmask) != 0) ||
3496 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3497 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3498 return;
3499 }
3500 portp = panelp->ports[(ioack >> 3)];
3501
3502 outb((MISR + portp->uartaddr), ioaddr);
3503 misr = inb(ioaddr + EREG_DATA);
3504 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003505 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 portp->stats.modem++;
3507 }
3508
3509 outb((EOSRR + portp->uartaddr), ioaddr);
3510 outb(0, (ioaddr + EREG_DATA));
3511}
3512
3513/*****************************************************************************/
3514/* SC26198 HARDWARE FUNCTIONS */
3515/*****************************************************************************/
3516
3517/*
3518 * These functions get/set/update the registers of the sc26198 UARTs.
3519 * Access to the sc26198 registers is via an address/data io port pair.
3520 * (Maybe should make this inline...)
3521 */
3522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003523static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524{
3525 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003526 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527}
3528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003529static void stl_sc26198setreg(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 outb(value, (portp->ioaddr + XP_DATA));
3533}
3534
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003535static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536{
3537 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3538 if (inb(portp->ioaddr + XP_DATA) != value) {
3539 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003540 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003542 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543}
3544
3545/*****************************************************************************/
3546
3547/*
3548 * Functions to get and set the sc26198 global registers.
3549 */
3550
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003551static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552{
3553 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003554 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555}
3556
3557#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003558static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559{
3560 outb(regnr, (portp->ioaddr + XP_ADDR));
3561 outb(value, (portp->ioaddr + XP_DATA));
3562}
3563#endif
3564
3565/*****************************************************************************/
3566
3567/*
3568 * Inbitialize the UARTs in a panel. We don't care what sort of board
3569 * these ports are on - since the port io registers are almost
3570 * identical when dealing with ports.
3571 */
3572
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003573static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574{
3575 int chipmask, i;
3576 int nrchips, ioaddr;
3577
Jiri Slabya0564e12006-12-08 02:38:37 -08003578 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579
3580 BRDENABLE(panelp->brdnr, panelp->pagenr);
3581
3582/*
3583 * Check that each chip is present and started up OK.
3584 */
3585 chipmask = 0;
3586 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3587 if (brdp->brdtype == BRD_ECHPCI)
3588 outb(panelp->pagenr, brdp->ioctrl);
3589
Jiri Slabyc62429d2006-12-08 02:39:14 -08003590 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 ioaddr = panelp->iobase + (i * 4);
3592 outb(SCCR, (ioaddr + XP_ADDR));
3593 outb(CR_RESETALL, (ioaddr + XP_DATA));
3594 outb(TSTR, (ioaddr + XP_ADDR));
3595 if (inb(ioaddr + XP_DATA) != 0) {
3596 printk("STALLION: sc26198 not responding, "
3597 "brd=%d panel=%d chip=%d\n",
3598 panelp->brdnr, panelp->panelnr, i);
3599 continue;
3600 }
3601 chipmask |= (0x1 << i);
3602 outb(GCCR, (ioaddr + XP_ADDR));
3603 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3604 outb(WDTRCR, (ioaddr + XP_ADDR));
3605 outb(0xff, (ioaddr + XP_DATA));
3606 }
3607
3608 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003609 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610}
3611
3612/*****************************************************************************/
3613
3614/*
3615 * Initialize hardware specific port registers.
3616 */
3617
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003618static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619{
Jiri Slabya0564e12006-12-08 02:38:37 -08003620 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3621 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
Jiri Slaby615e4a72006-12-08 02:38:38 -08003623 if ((brdp == NULL) || (panelp == NULL) ||
3624 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 return;
3626
3627 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3628 portp->uartaddr = (portp->portnr & 0x07) << 4;
3629 portp->pagenr = panelp->pagenr;
3630 portp->hwid = 0x1;
3631
3632 BRDENABLE(portp->brdnr, portp->pagenr);
3633 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3634 BRDDISABLE(portp->brdnr);
3635}
3636
3637/*****************************************************************************/
3638
3639/*
3640 * Set up the sc26198 registers for a port based on the termios port
3641 * settings.
3642 */
3643
Alan Cox606d0992006-12-08 02:38:45 -08003644static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003646 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 unsigned long flags;
3648 unsigned int baudrate;
3649 unsigned char mr0, mr1, mr2, clk;
3650 unsigned char imron, imroff, iopr, ipr;
3651
3652 mr0 = 0;
3653 mr1 = 0;
3654 mr2 = 0;
3655 clk = 0;
3656 iopr = 0;
3657 imron = 0;
3658 imroff = 0;
3659
3660 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003661 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 return;
3663
3664/*
3665 * Set up the RX char ignore mask with those RX error types we
3666 * can ignore.
3667 */
3668 portp->rxignoremsk = 0;
3669 if (tiosp->c_iflag & IGNPAR)
3670 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3671 SR_RXOVERRUN);
3672 if (tiosp->c_iflag & IGNBRK)
3673 portp->rxignoremsk |= SR_RXBREAK;
3674
3675 portp->rxmarkmsk = SR_RXOVERRUN;
3676 if (tiosp->c_iflag & (INPCK | PARMRK))
3677 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3678 if (tiosp->c_iflag & BRKINT)
3679 portp->rxmarkmsk |= SR_RXBREAK;
3680
3681/*
3682 * Go through the char size, parity and stop bits and set all the
3683 * option register appropriately.
3684 */
3685 switch (tiosp->c_cflag & CSIZE) {
3686 case CS5:
3687 mr1 |= MR1_CS5;
3688 break;
3689 case CS6:
3690 mr1 |= MR1_CS6;
3691 break;
3692 case CS7:
3693 mr1 |= MR1_CS7;
3694 break;
3695 default:
3696 mr1 |= MR1_CS8;
3697 break;
3698 }
3699
3700 if (tiosp->c_cflag & CSTOPB)
3701 mr2 |= MR2_STOP2;
3702 else
3703 mr2 |= MR2_STOP1;
3704
3705 if (tiosp->c_cflag & PARENB) {
3706 if (tiosp->c_cflag & PARODD)
3707 mr1 |= (MR1_PARENB | MR1_PARODD);
3708 else
3709 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003710 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
3713 mr1 |= MR1_ERRBLOCK;
3714
3715/*
3716 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3717 * space for hardware flow control and the like. This should be set to
3718 * VMIN.
3719 */
3720 mr2 |= MR2_RXFIFOHALF;
3721
3722/*
3723 * Calculate the baud rate timers. For now we will just assume that
3724 * the input and output baud are the same. The sc26198 has a fixed
3725 * baud rate table, so only discrete baud rates possible.
3726 */
3727 baudrate = tiosp->c_cflag & CBAUD;
3728 if (baudrate & CBAUDEX) {
3729 baudrate &= ~CBAUDEX;
3730 if ((baudrate < 1) || (baudrate > 4))
3731 tiosp->c_cflag &= ~CBAUDEX;
3732 else
3733 baudrate += 15;
3734 }
3735 baudrate = stl_baudrates[baudrate];
3736 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003737 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003739 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003741 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003743 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003745 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 baudrate = (portp->baud_base / portp->custom_divisor);
3747 }
3748 if (baudrate > STL_SC26198MAXBAUD)
3749 baudrate = STL_SC26198MAXBAUD;
3750
Jiri Slabyc62429d2006-12-08 02:39:14 -08003751 if (baudrate > 0)
3752 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 if (baudrate <= sc26198_baudtable[clk])
3754 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
3756/*
3757 * Check what form of modem signaling is required and set it up.
3758 */
3759 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003760 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 } else {
3762 iopr |= IOPR_DCDCOS;
3763 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003764 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765 }
3766
3767/*
3768 * Setup sc26198 enhanced modes if we can. In particular we want to
3769 * handle as much of the flow control as possible automatically. As
3770 * well as saving a few CPU cycles it will also greatly improve flow
3771 * control reliability.
3772 */
3773 if (tiosp->c_iflag & IXON) {
3774 mr0 |= MR0_SWFTX | MR0_SWFT;
3775 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003776 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003778
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 if (tiosp->c_iflag & IXOFF)
3780 mr0 |= MR0_SWFRX;
3781
3782 if (tiosp->c_cflag & CRTSCTS) {
3783 mr2 |= MR2_AUTOCTS;
3784 mr1 |= MR1_AUTORTS;
3785 }
3786
3787/*
3788 * All sc26198 register values calculated so go through and set
3789 * them all up.
3790 */
3791
Jiri Slabya0564e12006-12-08 02:38:37 -08003792 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003794 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3795 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3796 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3798 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
Alan Coxb65b5b52006-06-27 02:54:05 -07003800 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 BRDENABLE(portp->brdnr, portp->pagenr);
3802 stl_sc26198setreg(portp, IMR, 0);
3803 stl_sc26198updatereg(portp, MR0, mr0);
3804 stl_sc26198updatereg(portp, MR1, mr1);
3805 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3806 stl_sc26198updatereg(portp, MR2, mr2);
3807 stl_sc26198updatereg(portp, IOPIOR,
3808 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3809
3810 if (baudrate > 0) {
3811 stl_sc26198setreg(portp, TXCSR, clk);
3812 stl_sc26198setreg(portp, RXCSR, clk);
3813 }
3814
3815 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3816 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3817
3818 ipr = stl_sc26198getreg(portp, IPR);
3819 if (ipr & IPR_DCD)
3820 portp->sigs &= ~TIOCM_CD;
3821 else
3822 portp->sigs |= TIOCM_CD;
3823
3824 portp->imr = (portp->imr & ~imroff) | imron;
3825 stl_sc26198setreg(portp, IMR, portp->imr);
3826 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003827 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828}
3829
3830/*****************************************************************************/
3831
3832/*
3833 * Set the state of the DTR and RTS signals.
3834 */
3835
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003836static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
3838 unsigned char iopioron, iopioroff;
3839 unsigned long flags;
3840
Jiri Slabya0564e12006-12-08 02:38:37 -08003841 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3842 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
3844 iopioron = 0;
3845 iopioroff = 0;
3846 if (dtr == 0)
3847 iopioroff |= IPR_DTR;
3848 else if (dtr > 0)
3849 iopioron |= IPR_DTR;
3850 if (rts == 0)
3851 iopioroff |= IPR_RTS;
3852 else if (rts > 0)
3853 iopioron |= IPR_RTS;
3854
Alan Coxb65b5b52006-06-27 02:54:05 -07003855 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 BRDENABLE(portp->brdnr, portp->pagenr);
3857 stl_sc26198setreg(portp, IOPIOR,
3858 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3859 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003860 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861}
3862
3863/*****************************************************************************/
3864
3865/*
3866 * Return the state of the signals.
3867 */
3868
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003869static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870{
3871 unsigned char ipr;
3872 unsigned long flags;
3873 int sigs;
3874
Jiri Slabya0564e12006-12-08 02:38:37 -08003875 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876
Alan Coxb65b5b52006-06-27 02:54:05 -07003877 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 BRDENABLE(portp->brdnr, portp->pagenr);
3879 ipr = stl_sc26198getreg(portp, IPR);
3880 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003881 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882
3883 sigs = 0;
3884 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3885 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3886 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3887 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3888 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003889 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890}
3891
3892/*****************************************************************************/
3893
3894/*
3895 * Enable/Disable the Transmitter and/or Receiver.
3896 */
3897
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003898static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899{
3900 unsigned char ccr;
3901 unsigned long flags;
3902
Jiri Slabya0564e12006-12-08 02:38:37 -08003903 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904
3905 ccr = portp->crenable;
3906 if (tx == 0)
3907 ccr &= ~CR_TXENABLE;
3908 else if (tx > 0)
3909 ccr |= CR_TXENABLE;
3910 if (rx == 0)
3911 ccr &= ~CR_RXENABLE;
3912 else if (rx > 0)
3913 ccr |= CR_RXENABLE;
3914
Alan Coxb65b5b52006-06-27 02:54:05 -07003915 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 BRDENABLE(portp->brdnr, portp->pagenr);
3917 stl_sc26198setreg(portp, SCCR, ccr);
3918 BRDDISABLE(portp->brdnr);
3919 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003920 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921}
3922
3923/*****************************************************************************/
3924
3925/*
3926 * Start/stop the Transmitter and/or Receiver.
3927 */
3928
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003929static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930{
3931 unsigned char imr;
3932 unsigned long flags;
3933
Jiri Slabya0564e12006-12-08 02:38:37 -08003934 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935
3936 imr = portp->imr;
3937 if (tx == 0)
3938 imr &= ~IR_TXRDY;
3939 else if (tx == 1)
3940 imr |= IR_TXRDY;
3941 if (rx == 0)
3942 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3943 else if (rx > 0)
3944 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3945
Alan Coxb65b5b52006-06-27 02:54:05 -07003946 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 BRDENABLE(portp->brdnr, portp->pagenr);
3948 stl_sc26198setreg(portp, IMR, imr);
3949 BRDDISABLE(portp->brdnr);
3950 portp->imr = imr;
3951 if (tx > 0)
3952 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003953 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954}
3955
3956/*****************************************************************************/
3957
3958/*
3959 * Disable all interrupts from this port.
3960 */
3961
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003962static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963{
3964 unsigned long flags;
3965
Jiri Slabya0564e12006-12-08 02:38:37 -08003966 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Alan Coxb65b5b52006-06-27 02:54:05 -07003968 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 BRDENABLE(portp->brdnr, portp->pagenr);
3970 portp->imr = 0;
3971 stl_sc26198setreg(portp, IMR, 0);
3972 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003973 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974}
3975
3976/*****************************************************************************/
3977
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003978static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979{
3980 unsigned long flags;
3981
Jiri Slabya0564e12006-12-08 02:38:37 -08003982 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983
Alan Coxb65b5b52006-06-27 02:54:05 -07003984 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 BRDENABLE(portp->brdnr, portp->pagenr);
3986 if (len == 1) {
3987 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
3988 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003989 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003991
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003993 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994}
3995
3996/*****************************************************************************/
3997
3998/*
3999 * Take flow control actions...
4000 */
4001
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004002static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003{
4004 struct tty_struct *tty;
4005 unsigned long flags;
4006 unsigned char mr0;
4007
Jiri Slabya0564e12006-12-08 02:38:37 -08004008 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
Jiri Slaby615e4a72006-12-08 02:38:38 -08004010 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004012 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004013 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014 return;
4015
Alan Coxb65b5b52006-06-27 02:54:05 -07004016 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 BRDENABLE(portp->brdnr, portp->pagenr);
4018
4019 if (state) {
4020 if (tty->termios->c_iflag & IXOFF) {
4021 mr0 = stl_sc26198getreg(portp, MR0);
4022 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4023 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4024 mr0 |= MR0_SWFRX;
4025 portp->stats.rxxon++;
4026 stl_sc26198wait(portp);
4027 stl_sc26198setreg(portp, MR0, mr0);
4028 }
4029/*
4030 * Question: should we return RTS to what it was before? It may
4031 * have been set by an ioctl... Suppose not, since if you have
4032 * hardware flow control set then it is pretty silly to go and
4033 * set the RTS line by hand.
4034 */
4035 if (tty->termios->c_cflag & CRTSCTS) {
4036 stl_sc26198setreg(portp, MR1,
4037 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4038 stl_sc26198setreg(portp, IOPIOR,
4039 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4040 portp->stats.rxrtson++;
4041 }
4042 } else {
4043 if (tty->termios->c_iflag & IXOFF) {
4044 mr0 = stl_sc26198getreg(portp, MR0);
4045 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4046 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4047 mr0 &= ~MR0_SWFRX;
4048 portp->stats.rxxoff++;
4049 stl_sc26198wait(portp);
4050 stl_sc26198setreg(portp, MR0, mr0);
4051 }
4052 if (tty->termios->c_cflag & CRTSCTS) {
4053 stl_sc26198setreg(portp, MR1,
4054 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4055 stl_sc26198setreg(portp, IOPIOR,
4056 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4057 portp->stats.rxrtsoff++;
4058 }
4059 }
4060
4061 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004062 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004063 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064}
4065
4066/*****************************************************************************/
4067
4068/*
4069 * Send a flow control character.
4070 */
4071
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004072static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073{
4074 struct tty_struct *tty;
4075 unsigned long flags;
4076 unsigned char mr0;
4077
Jiri Slabya0564e12006-12-08 02:38:37 -08004078 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Jiri Slaby615e4a72006-12-08 02:38:38 -08004080 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004082 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004083 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 return;
4085
Alan Coxb65b5b52006-06-27 02:54:05 -07004086 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 BRDENABLE(portp->brdnr, portp->pagenr);
4088 if (state) {
4089 mr0 = stl_sc26198getreg(portp, MR0);
4090 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4091 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4092 mr0 |= MR0_SWFRX;
4093 portp->stats.rxxon++;
4094 stl_sc26198wait(portp);
4095 stl_sc26198setreg(portp, MR0, mr0);
4096 } else {
4097 mr0 = stl_sc26198getreg(portp, MR0);
4098 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4099 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4100 mr0 &= ~MR0_SWFRX;
4101 portp->stats.rxxoff++;
4102 stl_sc26198wait(portp);
4103 stl_sc26198setreg(portp, MR0, mr0);
4104 }
4105 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004106 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004107 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108}
4109
4110/*****************************************************************************/
4111
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004112static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
4114 unsigned long flags;
4115
Jiri Slabya0564e12006-12-08 02:38:37 -08004116 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Jiri Slaby615e4a72006-12-08 02:38:38 -08004118 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 return;
4120
Alan Coxb65b5b52006-06-27 02:54:05 -07004121 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 BRDENABLE(portp->brdnr, portp->pagenr);
4123 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4124 stl_sc26198setreg(portp, SCCR, portp->crenable);
4125 BRDDISABLE(portp->brdnr);
4126 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004127 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128}
4129
4130/*****************************************************************************/
4131
4132/*
4133 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02004134 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 * transmission or not... The sc26198 interrupt scheme cannot
4136 * determine when all data has actually drained, so we need to
4137 * check the port statusy register to be sure.
4138 */
4139
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004140static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141{
4142 unsigned long flags;
4143 unsigned char sr;
4144
Jiri Slabya0564e12006-12-08 02:38:37 -08004145 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Jiri Slaby615e4a72006-12-08 02:38:38 -08004147 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004148 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004150 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Alan Coxb65b5b52006-06-27 02:54:05 -07004152 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 BRDENABLE(portp->brdnr, portp->pagenr);
4154 sr = stl_sc26198getreg(portp, SR);
4155 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004156 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
Jesper Juhl014c2542006-01-15 02:37:08 +01004158 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159}
4160
4161/*****************************************************************************/
4162
4163/*
4164 * Delay for a small amount of time, to give the sc26198 a chance
4165 * to process a command...
4166 */
4167
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004168static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
4170 int i;
4171
Jiri Slabya0564e12006-12-08 02:38:37 -08004172 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Jiri Slaby615e4a72006-12-08 02:38:38 -08004174 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 return;
4176
Jiri Slabyc62429d2006-12-08 02:39:14 -08004177 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 stl_sc26198getglobreg(portp, TSTR);
4179}
4180
4181/*****************************************************************************/
4182
4183/*
4184 * If we are TX flow controlled and in IXANY mode then we may
4185 * need to unflow control here. We gotta do this because of the
4186 * automatic flow control modes of the sc26198.
4187 */
4188
Jiri Slaby60be4812006-12-08 02:38:40 -08004189static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190{
4191 unsigned char mr0;
4192
4193 mr0 = stl_sc26198getreg(portp, MR0);
4194 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4195 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4196 stl_sc26198wait(portp);
4197 stl_sc26198setreg(portp, MR0, mr0);
4198 clear_bit(ASYI_TXFLOWED, &portp->istate);
4199}
4200
4201/*****************************************************************************/
4202
4203/*
4204 * Interrupt service routine for sc26198 panels.
4205 */
4206
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004207static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004209 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 unsigned int iack;
4211
Alan Coxb65b5b52006-06-27 02:54:05 -07004212 spin_lock(&brd_lock);
4213
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214/*
4215 * Work around bug in sc26198 chip... Cannot have A6 address
4216 * line of UART high, else iack will be returned as 0.
4217 */
4218 outb(0, (iobase + 1));
4219
4220 iack = inb(iobase + XP_IACK);
4221 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4222
4223 if (iack & IVR_RXDATA)
4224 stl_sc26198rxisr(portp, iack);
4225 else if (iack & IVR_TXDATA)
4226 stl_sc26198txisr(portp);
4227 else
4228 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004229
4230 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231}
4232
4233/*****************************************************************************/
4234
4235/*
4236 * Transmit interrupt handler. This has gotta be fast! Handling TX
4237 * chars is pretty simple, stuff as many as possible from the TX buffer
4238 * into the sc26198 FIFO.
4239 * In practice it is possible that interrupts are enabled but that the
4240 * port has been hung up. Need to handle not having any TX buffer here,
4241 * this is done by using the side effect that head and tail will also
4242 * be NULL if the buffer has been freed.
4243 */
4244
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004245static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246{
Alan Coxd18a7502008-10-13 10:40:07 +01004247 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 unsigned int ioaddr;
4249 unsigned char mr0;
4250 int len, stlen;
4251 char *head, *tail;
4252
Jiri Slabya0564e12006-12-08 02:38:37 -08004253 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
4255 ioaddr = portp->ioaddr;
4256 head = portp->tx.head;
4257 tail = portp->tx.tail;
4258 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4259 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4260 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4261 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004262 tty = tty_port_tty_get(&portp->port);
4263 if (tty) {
4264 tty_wakeup(tty);
4265 tty_kref_put(tty);
4266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 }
4268
4269 if (len == 0) {
4270 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4271 mr0 = inb(ioaddr + XP_DATA);
4272 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4273 portp->imr &= ~IR_TXRDY;
4274 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4275 outb(portp->imr, (ioaddr + XP_DATA));
4276 clear_bit(ASYI_TXBUSY, &portp->istate);
4277 } else {
4278 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4279 outb(mr0, (ioaddr + XP_DATA));
4280 }
4281 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004282 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004284 stlen = min_t(unsigned int, len,
4285 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 outb(GTXFIFO, (ioaddr + XP_ADDR));
4287 outsb((ioaddr + XP_DATA), tail, stlen);
4288 len -= stlen;
4289 tail += stlen;
4290 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4291 tail = portp->tx.buf;
4292 if (len > 0) {
4293 outsb((ioaddr + XP_DATA), tail, len);
4294 tail += len;
4295 }
4296 portp->tx.tail = tail;
4297 }
4298}
4299
4300/*****************************************************************************/
4301
4302/*
4303 * Receive character interrupt handler. Determine if we have good chars
4304 * or bad chars and then process appropriately. Good chars are easy
4305 * just shove the lot into the RX buffer and set all status byte to 0.
4306 * If a bad RX char then process as required. This routine needs to be
4307 * fast! In practice it is possible that we get an interrupt on a port
4308 * that is closed. This can happen on hangups - since they completely
4309 * shutdown a port not in user context. Need to handle this case.
4310 */
4311
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004312static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313{
4314 struct tty_struct *tty;
4315 unsigned int len, buflen, ioaddr;
4316
Jiri Slabya0564e12006-12-08 02:38:37 -08004317 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Alan Coxd18a7502008-10-13 10:40:07 +01004319 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320 ioaddr = portp->ioaddr;
4321 outb(GIBCR, (ioaddr + XP_ADDR));
4322 len = inb(ioaddr + XP_DATA) + 1;
4323
4324 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004325 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004326 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 outb(GRXFIFO, (ioaddr + XP_ADDR));
4328 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4329 portp->stats.rxlost += len;
4330 portp->stats.rxtotal += len;
4331 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004332 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004334 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004336 tty_prepare_flip_string(tty, &ptr, len);
4337 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 tty_schedule_flip(tty);
4339 portp->stats.rxtotal += len;
4340 }
4341 }
4342 } else {
4343 stl_sc26198rxbadchars(portp);
4344 }
4345
4346/*
4347 * If we are TX flow controlled and in IXANY mode then we may need
4348 * to unflow control here. We gotta do this because of the automatic
4349 * flow control modes of the sc26198.
4350 */
4351 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004352 if ((tty != NULL) &&
4353 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354 (tty->termios->c_iflag & IXANY)) {
4355 stl_sc26198txunflow(portp, tty);
4356 }
4357 }
Alan Coxd18a7502008-10-13 10:40:07 +01004358 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359}
4360
4361/*****************************************************************************/
4362
4363/*
4364 * Process an RX bad character.
4365 */
4366
Jiri Slaby60be4812006-12-08 02:38:40 -08004367static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368{
4369 struct tty_struct *tty;
4370 unsigned int ioaddr;
4371
Alan Coxd18a7502008-10-13 10:40:07 +01004372 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 ioaddr = portp->ioaddr;
4374
4375 if (status & SR_RXPARITY)
4376 portp->stats.rxparity++;
4377 if (status & SR_RXFRAMING)
4378 portp->stats.rxframing++;
4379 if (status & SR_RXOVERRUN)
4380 portp->stats.rxoverrun++;
4381 if (status & SR_RXBREAK)
4382 portp->stats.rxbreaks++;
4383
Jiri Slaby615e4a72006-12-08 02:38:38 -08004384 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 ((portp->rxignoremsk & status) == 0)) {
4386 if (portp->rxmarkmsk & status) {
4387 if (status & SR_RXBREAK) {
4388 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004389 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390 do_SAK(tty);
4391 BRDENABLE(portp->brdnr, portp->pagenr);
4392 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004393 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004395 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004397 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004399 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004401 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Alan Cox33f0f882006-01-09 20:54:13 -08004404 tty_insert_flip_char(tty, ch, status);
4405 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
4407 if (status == 0)
4408 portp->stats.rxtotal++;
4409 }
Alan Coxd18a7502008-10-13 10:40:07 +01004410 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411}
4412
4413/*****************************************************************************/
4414
4415/*
4416 * Process all characters in the RX FIFO of the UART. Check all char
4417 * status bytes as well, and process as required. We need to check
4418 * all bytes in the FIFO, in case some more enter the FIFO while we
4419 * are here. To get the exact character error type we need to switch
4420 * into CHAR error mode (that is why we need to make sure we empty
4421 * the FIFO).
4422 */
4423
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004424static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425{
4426 unsigned char status, mr1;
4427 char ch;
4428
4429/*
4430 * To get the precise error type for each character we must switch
4431 * back into CHAR error mode.
4432 */
4433 mr1 = stl_sc26198getreg(portp, MR1);
4434 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4435
4436 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4437 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4438 ch = stl_sc26198getreg(portp, RXFIFO);
4439 stl_sc26198rxbadch(portp, status, ch);
4440 }
4441
4442/*
4443 * To get correct interrupt class we must switch back into BLOCK
4444 * error mode.
4445 */
4446 stl_sc26198setreg(portp, MR1, mr1);
4447}
4448
4449/*****************************************************************************/
4450
4451/*
4452 * Other interrupt handler. This includes modem signals, flow
4453 * control actions, etc. Most stuff is left to off-level interrupt
4454 * processing time.
4455 */
4456
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004457static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458{
4459 unsigned char cir, ipr, xisr;
4460
Jiri Slabya0564e12006-12-08 02:38:37 -08004461 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004462
4463 cir = stl_sc26198getglobreg(portp, CIR);
4464
4465 switch (cir & CIR_SUBTYPEMASK) {
4466 case CIR_SUBCOS:
4467 ipr = stl_sc26198getreg(portp, IPR);
4468 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004469 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 portp->stats.modem++;
4471 }
4472 break;
4473 case CIR_SUBXONXOFF:
4474 xisr = stl_sc26198getreg(portp, XISR);
4475 if (xisr & XISR_RXXONGOT) {
4476 set_bit(ASYI_TXFLOWED, &portp->istate);
4477 portp->stats.txxoff++;
4478 }
4479 if (xisr & XISR_RXXOFFGOT) {
4480 clear_bit(ASYI_TXFLOWED, &portp->istate);
4481 portp->stats.txxon++;
4482 }
4483 break;
4484 case CIR_SUBBREAK:
4485 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4486 stl_sc26198rxbadchars(portp);
4487 break;
4488 default:
4489 break;
4490 }
4491}
4492
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004493static void stl_free_isabrds(void)
4494{
4495 struct stlbrd *brdp;
4496 unsigned int i;
4497
4498 for (i = 0; i < stl_nrbrds; i++) {
4499 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4500 continue;
4501
4502 free_irq(brdp->irq, brdp);
4503
4504 stl_cleanup_panels(brdp);
4505
4506 release_region(brdp->ioaddr1, brdp->iosize1);
4507 if (brdp->iosize2 > 0)
4508 release_region(brdp->ioaddr2, brdp->iosize2);
4509
4510 kfree(brdp);
4511 stl_brds[i] = NULL;
4512 }
4513}
4514
Jiri Slaby23b85a12006-12-08 02:38:40 -08004515/*
4516 * Loadable module initialization stuff.
4517 */
4518static int __init stallion_module_init(void)
4519{
Jiri Slaby843b5682006-12-08 02:39:12 -08004520 struct stlbrd *brdp;
4521 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004522 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004523 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004524
4525 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4526
4527 spin_lock_init(&stallion_lock);
4528 spin_lock_init(&brd_lock);
4529
Jiri Slabye4151092007-06-08 13:46:52 -07004530 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4531 if (!stl_serial) {
4532 retval = -ENOMEM;
4533 goto err;
4534 }
4535
4536 stl_serial->owner = THIS_MODULE;
4537 stl_serial->driver_name = stl_drvname;
4538 stl_serial->name = "ttyE";
4539 stl_serial->major = STL_SERIALMAJOR;
4540 stl_serial->minor_start = 0;
4541 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4542 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4543 stl_serial->init_termios = stl_deftermios;
4544 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4545 tty_set_operations(stl_serial, &stl_ops);
4546
4547 retval = tty_register_driver(stl_serial);
4548 if (retval) {
4549 printk("STALLION: failed to register serial driver\n");
4550 goto err_frtty;
4551 }
4552
Jiri Slaby843b5682006-12-08 02:39:12 -08004553/*
4554 * Find any dynamically supported boards. That is via module load
4555 * line options.
4556 */
4557 for (i = stl_nrbrds; i < stl_nargs; i++) {
4558 memset(&conf, 0, sizeof(conf));
4559 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4560 continue;
4561 if ((brdp = stl_allocbrd()) == NULL)
4562 continue;
4563 brdp->brdnr = i;
4564 brdp->brdtype = conf.brdtype;
4565 brdp->ioaddr1 = conf.ioaddr1;
4566 brdp->ioaddr2 = conf.ioaddr2;
4567 brdp->irq = conf.irq;
4568 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004569 stl_brds[brdp->brdnr] = brdp;
4570 if (stl_brdinit(brdp)) {
4571 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004572 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004573 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004574 for (j = 0; j < brdp->nrports; j++)
4575 tty_register_device(stl_serial,
4576 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004577 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004578 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004579 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004580
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004581 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004582 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004583 if (retval && stl_nrbrds == 0) {
4584 printk(KERN_ERR "STALLION: can't register pci driver\n");
4585 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004586 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004587
4588/*
4589 * Set up a character driver for per board stuff. This is mainly used
4590 * to do stats ioctls on the ports.
4591 */
4592 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4593 printk("STALLION: failed to register serial board device\n");
4594
4595 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004596 if (IS_ERR(stallion_class))
4597 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004598 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004599 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4600 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004601
Jiri Slaby23b85a12006-12-08 02:38:40 -08004602 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004603err_unrtty:
4604 tty_unregister_driver(stl_serial);
4605err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004606 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004607err:
4608 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004609}
4610
4611static void __exit stallion_module_exit(void)
4612{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004613 struct stlbrd *brdp;
4614 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004615
4616 pr_debug("cleanup_module()\n");
4617
4618 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4619 stl_drvversion);
4620
4621/*
4622 * Free up all allocated resources used by the ports. This includes
4623 * memory and interrupts. As part of this process we will also do
4624 * a hangup on every open port - to try to flush out any processes
4625 * hanging onto ports.
4626 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004627 for (i = 0; i < stl_nrbrds; i++) {
4628 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4629 continue;
4630 for (j = 0; j < brdp->nrports; j++)
4631 tty_unregister_device(stl_serial,
4632 brdp->brdnr * STL_MAXPORTS + j);
4633 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004634
Jiri Slaby23b85a12006-12-08 02:38:40 -08004635 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004636 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004637 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004638 class_destroy(stallion_class);
4639
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004640 pci_unregister_driver(&stl_pcidriver);
4641
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004642 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004643
4644 tty_unregister_driver(stl_serial);
4645 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004646}
4647
4648module_init(stallion_module_init);
4649module_exit(stallion_module_exit);
4650
4651MODULE_AUTHOR("Greg Ungerer");
4652MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4653MODULE_LICENSE("GPL");