blob: 4fff5cd3b163ac315bba6a0e7f28553fcce0da54 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/device.h>
44#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080045#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#include <asm/io.h>
48#include <asm/uaccess.h>
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52/*****************************************************************************/
53
54/*
55 * Define different board types. Use the standard Stallion "assigned"
56 * board numbers. Boards supported in this driver are abbreviated as
57 * EIO = EasyIO and ECH = EasyConnection 8/32.
58 */
59#define BRD_EASYIO 20
60#define BRD_ECH 21
61#define BRD_ECHMC 22
62#define BRD_ECHPCI 26
63#define BRD_ECH64PCI 27
64#define BRD_EASYIOPCI 28
65
Jiri Slaby843b5682006-12-08 02:39:12 -080066struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080067 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 int ioaddr1;
69 int ioaddr2;
70 unsigned long memaddr;
71 int irq;
72 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
Jiri Slaby843b5682006-12-08 02:39:12 -080075static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/*****************************************************************************/
78
79/*
80 * Define some important driver characteristics. Device major numbers
81 * allocated as per Linux Device Registry.
82 */
83#ifndef STL_SIOMEMMAJOR
84#define STL_SIOMEMMAJOR 28
85#endif
86#ifndef STL_SERIALMAJOR
87#define STL_SERIALMAJOR 24
88#endif
89#ifndef STL_CALLOUTMAJOR
90#define STL_CALLOUTMAJOR 25
91#endif
92
93/*
94 * Set the TX buffer size. Bigger is better, but we don't want
95 * to chew too much memory with buffers!
96 */
97#define STL_TXBUFLOW 512
98#define STL_TXBUFSIZE 4096
99
100/*****************************************************************************/
101
102/*
103 * Define our local driver identity first. Set up stuff to deal with
104 * all the local structures required by a serial tty driver.
105 */
106static char *stl_drvtitle = "Stallion Multiport Serial Driver";
107static char *stl_drvname = "stallion";
108static char *stl_drvversion = "5.6.0";
109
110static struct tty_driver *stl_serial;
111
112/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 * Define a local default termios struct. All ports will be created
114 * with this termios initially. Basically all it defines is a raw port
115 * at 9600, 8 data bits, 1 stop bit.
116 */
Alan Cox606d0992006-12-08 02:38:45 -0800117static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
119 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800120 .c_ispeed = 9600,
121 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122};
123
124/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 * Define global place to put buffer overflow characters.
126 */
127static char stl_unwanted[SC26198_RXFIFOSIZE];
128
129/*****************************************************************************/
130
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800131static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800132static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Alan Cox31f35932009-01-02 13:45:05 +0000134static const struct tty_port_operations stl_port_ops;
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136/*
137 * Per board state flags. Used with the state field of the board struct.
138 * Not really much here!
139 */
140#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800141#define STL_PROBED 0x2
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144/*
145 * Define the port structure istate flags. These set of flags are
146 * modified at interrupt time - so setting and reseting them needs
147 * to be atomic. Use the bit clear/setting routines for this.
148 */
149#define ASYI_TXBUSY 1
150#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800151#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153/*
154 * Define an array of board names as printable strings. Handy for
155 * referencing boards when printing trace and stuff.
156 */
157static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 "EasyIO",
179 "EC8/32-AT",
180 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800181 NULL,
182 NULL,
183 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 "EC8/32-PCI",
185 "EC8/64-PCI",
186 "EasyIO-PCI",
187};
188
189/*****************************************************************************/
190
191/*
192 * Define some string labels for arguments passed from the module
193 * load line. These allow for easy board definitions, and easy
194 * modification of the io, memory and irq resoucres.
195 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800196static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197static char *board0[4];
198static char *board1[4];
199static char *board2[4];
200static char *board3[4];
201
202static char **stl_brdsp[] = {
203 (char **) &board0,
204 (char **) &board1,
205 (char **) &board2,
206 (char **) &board3
207};
208
209/*
210 * Define a set of common board names, and types. This is used to
211 * parse any module arguments.
212 */
213
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800214static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 char *name;
216 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800217} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 { "easyio", BRD_EASYIO },
219 { "eio", BRD_EASYIO },
220 { "20", BRD_EASYIO },
221 { "ec8/32", BRD_ECH },
222 { "ec8/32-at", BRD_ECH },
223 { "ec8/32-isa", BRD_ECH },
224 { "ech", BRD_ECH },
225 { "echat", BRD_ECH },
226 { "21", BRD_ECH },
227 { "ec8/32-mc", BRD_ECHMC },
228 { "ec8/32-mca", BRD_ECHMC },
229 { "echmc", BRD_ECHMC },
230 { "echmca", BRD_ECHMC },
231 { "22", BRD_ECHMC },
232 { "ec8/32-pc", BRD_ECHPCI },
233 { "ec8/32-pci", BRD_ECHPCI },
234 { "26", BRD_ECHPCI },
235 { "ec8/64-pc", BRD_ECH64PCI },
236 { "ec8/64-pci", BRD_ECH64PCI },
237 { "ech-pci", BRD_ECH64PCI },
238 { "echpci", BRD_ECH64PCI },
239 { "echpc", BRD_ECH64PCI },
240 { "27", BRD_ECH64PCI },
241 { "easyio-pc", BRD_EASYIOPCI },
242 { "easyio-pci", BRD_EASYIOPCI },
243 { "eio-pci", BRD_EASYIOPCI },
244 { "eiopci", BRD_EASYIOPCI },
245 { "28", BRD_EASYIOPCI },
246};
247
248/*
249 * Define the module agruments.
250 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252module_param_array(board0, charp, &stl_nargs, 0);
253MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
254module_param_array(board1, charp, &stl_nargs, 0);
255MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
256module_param_array(board2, charp, &stl_nargs, 0);
257MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
258module_param_array(board3, charp, &stl_nargs, 0);
259MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
260
261/*****************************************************************************/
262
263/*
264 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
265 * to the directly accessible io ports of these boards (not the uarts -
266 * they are in cd1400.h and sc26198.h).
267 */
268#define EIO_8PORTRS 0x04
269#define EIO_4PORTRS 0x05
270#define EIO_8PORTDI 0x00
271#define EIO_8PORTM 0x06
272#define EIO_MK3 0x03
273#define EIO_IDBITMASK 0x07
274
275#define EIO_BRDMASK 0xf0
276#define ID_BRD4 0x10
277#define ID_BRD8 0x20
278#define ID_BRD16 0x30
279
280#define EIO_INTRPEND 0x08
281#define EIO_INTEDGE 0x00
282#define EIO_INTLEVEL 0x08
283#define EIO_0WS 0x10
284
285#define ECH_ID 0xa0
286#define ECH_IDBITMASK 0xe0
287#define ECH_BRDENABLE 0x08
288#define ECH_BRDDISABLE 0x00
289#define ECH_INTENABLE 0x01
290#define ECH_INTDISABLE 0x00
291#define ECH_INTLEVEL 0x02
292#define ECH_INTEDGE 0x00
293#define ECH_INTRPEND 0x01
294#define ECH_BRDRESET 0x01
295
296#define ECHMC_INTENABLE 0x01
297#define ECHMC_BRDRESET 0x02
298
299#define ECH_PNLSTATUS 2
300#define ECH_PNL16PORT 0x20
301#define ECH_PNLIDMASK 0x07
302#define ECH_PNLXPID 0x40
303#define ECH_PNLINTRPEND 0x80
304
305#define ECH_ADDR2MASK 0x1e0
306
307/*
308 * Define the vector mapping bits for the programmable interrupt board
309 * hardware. These bits encode the interrupt for the board to use - it
310 * is software selectable (except the EIO-8M).
311 */
312static unsigned char stl_vecmap[] = {
313 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
314 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
315};
316
317/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700318 * Lock ordering is that you may not take stallion_lock holding
319 * brd_lock.
320 */
321
322static spinlock_t brd_lock; /* Guard the board mapping */
323static spinlock_t stallion_lock; /* Guard the tty driver */
324
325/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 * Set up enable and disable macros for the ECH boards. They require
327 * the secondary io address space to be activated and deactivated.
328 * This way all ECH boards can share their secondary io region.
329 * If this is an ECH-PCI board then also need to set the page pointer
330 * to point to the correct page.
331 */
332#define BRDENABLE(brdnr,pagenr) \
333 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
334 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
335 stl_brds[(brdnr)]->ioctrl); \
336 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
337 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
338
339#define BRDDISABLE(brdnr) \
340 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
341 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
342 stl_brds[(brdnr)]->ioctrl);
343
344#define STL_CD1400MAXBAUD 230400
345#define STL_SC26198MAXBAUD 460800
346
347#define STL_BAUDBASE 115200
348#define STL_CLOSEDELAY (5 * HZ / 10)
349
350/*****************************************************************************/
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352/*
353 * Define the Stallion PCI vendor and device IDs.
354 */
355#ifndef PCI_VENDOR_ID_STALLION
356#define PCI_VENDOR_ID_STALLION 0x124d
357#endif
358#ifndef PCI_DEVICE_ID_ECHPCI832
359#define PCI_DEVICE_ID_ECHPCI832 0x0000
360#endif
361#ifndef PCI_DEVICE_ID_ECHPCI864
362#define PCI_DEVICE_ID_ECHPCI864 0x0002
363#endif
364#ifndef PCI_DEVICE_ID_EIOPCI
365#define PCI_DEVICE_ID_EIOPCI 0x0003
366#endif
367
368/*
369 * Define structure to hold all Stallion PCI boards.
370 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800372static struct pci_device_id stl_pcibrds[] = {
373 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
374 .driver_data = BRD_ECH64PCI },
375 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
376 .driver_data = BRD_EASYIOPCI },
377 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
378 .driver_data = BRD_ECHPCI },
379 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
380 .driver_data = BRD_ECHPCI },
381 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800383MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385/*****************************************************************************/
386
387/*
388 * Define macros to extract a brd/port number from a minor number.
389 */
390#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
391#define MINOR2PORT(min) ((min) & 0x3f)
392
393/*
394 * Define a baud rate table that converts termios baud rate selector
395 * into the actual baud rate value. All baud rate calculations are
396 * based on the actual baud rate required.
397 */
398static unsigned int stl_baudrates[] = {
399 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
400 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
401};
402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403/*****************************************************************************/
404
405/*
406 * Declare all those functions in this driver!
407 */
408
Alan Cox894cb912009-10-13 16:34:15 +0100409static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800410static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100411static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800412static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414/*
415 * CD1400 uart specific handling functions.
416 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400getreg(struct stlport *portp, int regnr);
419static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
420static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
421static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800422static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800423static int stl_cd1400getsignals(struct stlport *portp);
424static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
425static void stl_cd1400ccrwait(struct stlport *portp);
426static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
427static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
428static void stl_cd1400disableintrs(struct stlport *portp);
429static void stl_cd1400sendbreak(struct stlport *portp, int len);
430static void stl_cd1400flowctrl(struct stlport *portp, int state);
431static void stl_cd1400sendflow(struct stlport *portp, int state);
432static void stl_cd1400flush(struct stlport *portp);
433static int stl_cd1400datastate(struct stlport *portp);
434static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
435static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
436static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
437static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
438static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800440static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442/*
443 * SC26198 uart specific handling functions.
444 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800445static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getreg(struct stlport *portp, int regnr);
447static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
448static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
449static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
450static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800451static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800452static int stl_sc26198getsignals(struct stlport *portp);
453static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
454static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
455static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
456static void stl_sc26198disableintrs(struct stlport *portp);
457static void stl_sc26198sendbreak(struct stlport *portp, int len);
458static void stl_sc26198flowctrl(struct stlport *portp, int state);
459static void stl_sc26198sendflow(struct stlport *portp, int state);
460static void stl_sc26198flush(struct stlport *portp);
461static int stl_sc26198datastate(struct stlport *portp);
462static void stl_sc26198wait(struct stlport *portp);
463static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
464static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
465static void stl_sc26198txisr(struct stlport *port);
466static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
467static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
468static void stl_sc26198rxbadchars(struct stlport *portp);
469static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471/*****************************************************************************/
472
473/*
474 * Generic UART support structure.
475 */
476typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800477 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
478 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800479 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800480 int (*getsignals)(struct stlport *portp);
481 void (*setsignals)(struct stlport *portp, int dtr, int rts);
482 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
483 void (*startrxtx)(struct stlport *portp, int rx, int tx);
484 void (*disableintrs)(struct stlport *portp);
485 void (*sendbreak)(struct stlport *portp, int len);
486 void (*flowctrl)(struct stlport *portp, int state);
487 void (*sendflow)(struct stlport *portp, int state);
488 void (*flush)(struct stlport *portp);
489 int (*datastate)(struct stlport *portp);
490 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491} uart_t;
492
493/*
494 * Define some macros to make calling these functions nice and clean.
495 */
496#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
497#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
498#define stl_setport (* ((uart_t *) portp->uartp)->setport)
499#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
500#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
501#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
502#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
503#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
504#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
505#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
506#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
507#define stl_flush (* ((uart_t *) portp->uartp)->flush)
508#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
509
510/*****************************************************************************/
511
512/*
513 * CD1400 UART specific data initialization.
514 */
515static uart_t stl_cd1400uart = {
516 stl_cd1400panelinit,
517 stl_cd1400portinit,
518 stl_cd1400setport,
519 stl_cd1400getsignals,
520 stl_cd1400setsignals,
521 stl_cd1400enablerxtx,
522 stl_cd1400startrxtx,
523 stl_cd1400disableintrs,
524 stl_cd1400sendbreak,
525 stl_cd1400flowctrl,
526 stl_cd1400sendflow,
527 stl_cd1400flush,
528 stl_cd1400datastate,
529 stl_cd1400eiointr
530};
531
532/*
533 * Define the offsets within the register bank of a cd1400 based panel.
534 * These io address offsets are common to the EasyIO board as well.
535 */
536#define EREG_ADDR 0
537#define EREG_DATA 4
538#define EREG_RXACK 5
539#define EREG_TXACK 6
540#define EREG_MDACK 7
541
542#define EREG_BANKSIZE 8
543
544#define CD1400_CLK 25000000
545#define CD1400_CLK8M 20000000
546
547/*
548 * Define the cd1400 baud rate clocks. These are used when calculating
549 * what clock and divisor to use for the required baud rate. Also
550 * define the maximum baud rate allowed, and the default base baud.
551 */
552static int stl_cd1400clkdivs[] = {
553 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
554};
555
556/*****************************************************************************/
557
558/*
559 * SC26198 UART specific data initization.
560 */
561static uart_t stl_sc26198uart = {
562 stl_sc26198panelinit,
563 stl_sc26198portinit,
564 stl_sc26198setport,
565 stl_sc26198getsignals,
566 stl_sc26198setsignals,
567 stl_sc26198enablerxtx,
568 stl_sc26198startrxtx,
569 stl_sc26198disableintrs,
570 stl_sc26198sendbreak,
571 stl_sc26198flowctrl,
572 stl_sc26198sendflow,
573 stl_sc26198flush,
574 stl_sc26198datastate,
575 stl_sc26198intr
576};
577
578/*
579 * Define the offsets within the register bank of a sc26198 based panel.
580 */
581#define XP_DATA 0
582#define XP_ADDR 1
583#define XP_MODID 2
584#define XP_STATUS 2
585#define XP_IACK 3
586
587#define XP_BANKSIZE 4
588
589/*
590 * Define the sc26198 baud rate table. Offsets within the table
591 * represent the actual baud rate selector of sc26198 registers.
592 */
593static unsigned int sc26198_baudtable[] = {
594 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
595 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
596 230400, 460800, 921600
597};
598
Tobias Klauserfe971072006-01-09 20:54:02 -0800599#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601/*****************************************************************************/
602
603/*
604 * Define the driver info for a user level control device. Used mainly
605 * to get at port stats - only not using the port device itself.
606 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700607static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 .owner = THIS_MODULE,
Alan Cox894cb912009-10-13 16:34:15 +0100609 .unlocked_ioctl = stl_memioctl,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200610 .llseek = noop_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800613static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800615static void stl_cd_change(struct stlport *portp)
616{
617 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100618 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800619
Alan Coxd18a7502008-10-13 10:40:07 +0100620 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800621 return;
622
623 portp->sigs = stl_getsignals(portp);
624
625 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100626 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800627
628 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100629 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100630 tty_hangup(tty);
631 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800632}
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 * Check for any arguments passed in on the module load command line.
636 */
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638/*****************************************************************************/
639
640/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 * Parse the supplied argument string, into the board conf struct.
642 */
643
Jiri Slaby40e82652006-12-08 02:38:41 -0800644static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800647 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slabya0564e12006-12-08 02:38:37 -0800649 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Jiri Slaby615e4a72006-12-08 02:38:38 -0800651 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Jiri Slabyc62429d2006-12-08 02:39:14 -0800654 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800655 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Jiri Slabyc62429d2006-12-08 02:39:14 -0800657 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
659 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800660
Tobias Klauserfe971072006-01-09 20:54:02 -0800661 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800663 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
665
666 confp->brdtype = stl_brdstr[i].type;
667
668 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800669 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800670 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 i++;
672 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800673 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800674 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 i++;
676 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800677 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800678 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100679 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
682/*****************************************************************************/
683
684/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 * Allocate a new board structure. Fill out the basic info in it.
686 */
687
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800688static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800692 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800693 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700694 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800695 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800696 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100700 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703/*****************************************************************************/
704
Alan Cox047e9652009-11-30 13:17:03 +0000705static int stl_activate(struct tty_port *port, struct tty_struct *tty)
706{
707 struct stlport *portp = container_of(port, struct stlport, port);
708 if (!portp->tx.buf) {
709 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
710 if (!portp->tx.buf)
711 return -ENOMEM;
712 portp->tx.head = portp->tx.buf;
713 portp->tx.tail = portp->tx.buf;
714 }
715 stl_setport(portp, tty->termios);
716 portp->sigs = stl_getsignals(portp);
717 stl_setsignals(portp, 1, 1);
718 stl_enablerxtx(portp, 1, 1);
719 stl_startrxtx(portp, 1, 0);
720 return 0;
721}
722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723static int stl_open(struct tty_struct *tty, struct file *filp)
724{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800725 struct stlport *portp;
726 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800727 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000728 int portnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Jiri Slabya0564e12006-12-08 02:38:37 -0800730 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
732 minordev = tty->index;
733 brdnr = MINOR2BRD(minordev);
734 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100735 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800737 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100738 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800741 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800742 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 break;
744 if (minordev < brdp->panels[panelnr]->nrports) {
745 portnr = minordev;
746 break;
747 }
748 minordev -= brdp->panels[panelnr]->nrports;
749 }
750 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100751 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800754 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100755 return -ENODEV;
Alan Coxa2d1e352010-04-23 16:01:18 +0100756
757 tty->driver_data = portp;
Alan Cox047e9652009-11-30 13:17:03 +0000758 return tty_port_open(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760}
761
762/*****************************************************************************/
763
Alan Cox31f35932009-01-02 13:45:05 +0000764static int stl_carrier_raised(struct tty_port *port)
765{
766 struct stlport *portp = container_of(port, struct stlport, port);
767 return (portp->sigs & TIOCM_CD) ? 1 : 0;
768}
769
Alan Coxfcc8ac12009-06-11 12:24:17 +0100770static void stl_dtr_rts(struct tty_port *port, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771{
Alan Cox4350f3f2009-01-02 13:46:24 +0000772 struct stlport *portp = container_of(port, struct stlport, port);
773 /* Takes brd_lock internally */
Alan Coxfcc8ac12009-06-11 12:24:17 +0100774 stl_setsignals(portp, on, on);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775}
776
777/*****************************************************************************/
778
Jiri Slaby96b066b2006-12-08 02:38:42 -0800779static void stl_flushbuffer(struct tty_struct *tty)
780{
781 struct stlport *portp;
782
783 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
784
Jiri Slaby96b066b2006-12-08 02:38:42 -0800785 portp = tty->driver_data;
786 if (portp == NULL)
787 return;
788
789 stl_flush(portp);
790 tty_wakeup(tty);
791}
792
793/*****************************************************************************/
794
795static void stl_waituntilsent(struct tty_struct *tty, int timeout)
796{
797 struct stlport *portp;
798 unsigned long tend;
799
800 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
801
Jiri Slaby96b066b2006-12-08 02:38:42 -0800802 portp = tty->driver_data;
803 if (portp == NULL)
804 return;
805
806 if (timeout == 0)
807 timeout = HZ;
808 tend = jiffies + timeout;
809
810 while (stl_datastate(portp)) {
811 if (signal_pending(current))
812 break;
813 msleep_interruptible(20);
814 if (time_after_eq(jiffies, tend))
815 break;
816 }
817}
818
819/*****************************************************************************/
820
Alan Cox047e9652009-11-30 13:17:03 +0000821static void stl_shutdown(struct tty_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
Alan Cox047e9652009-11-30 13:17:03 +0000823 struct stlport *portp = container_of(port, struct stlport, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 stl_disableintrs(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 stl_enablerxtx(portp, 0, 0);
Alan Cox047e9652009-11-30 13:17:03 +0000826 stl_flush(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800828 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800830 portp->tx.buf = NULL;
831 portp->tx.head = NULL;
832 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 }
Alan Cox047e9652009-11-30 13:17:03 +0000834}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Alan Cox047e9652009-11-30 13:17:03 +0000836static void stl_close(struct tty_struct *tty, struct file *filp)
837{
838 struct stlport*portp;
839 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
840
841 portp = tty->driver_data;
Alan Coxa2d1e352010-04-23 16:01:18 +0100842 if(portp == NULL)
843 return;
Alan Cox047e9652009-11-30 13:17:03 +0000844 tty_port_close(&portp->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845}
846
847/*****************************************************************************/
848
849/*
850 * Write routine. Take data and stuff it in to the TX ring queue.
851 * If transmit interrupts are not running then start them.
852 */
853
854static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
855{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800856 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 unsigned int len, stlen;
858 unsigned char *chbuf;
859 char *head, *tail;
860
Jiri Slabya0564e12006-12-08 02:38:37 -0800861 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800864 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100865 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800866 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100867 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
869/*
870 * If copying direct from user space we must cater for page faults,
871 * causing us to "sleep" here for a while. To handle this copy in all
872 * the data we need now, into a local buffer. Then when we got it all
873 * copy it into the TX buffer.
874 */
875 chbuf = (unsigned char *) buf;
876
877 head = portp->tx.head;
878 tail = portp->tx.tail;
879 if (head >= tail) {
880 len = STL_TXBUFSIZE - (head - tail) - 1;
881 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
882 } else {
883 len = tail - head - 1;
884 stlen = len;
885 }
886
Jiri Slaby843b5682006-12-08 02:39:12 -0800887 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 count = 0;
889 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800890 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 memcpy(head, chbuf, stlen);
892 len -= stlen;
893 chbuf += stlen;
894 count += stlen;
895 head += stlen;
896 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
897 head = portp->tx.buf;
898 stlen = tail - head;
899 }
900 }
901 portp->tx.head = head;
902
903 clear_bit(ASYI_TXLOW, &portp->istate);
904 stl_startrxtx(portp, -1, 1);
905
Jesper Juhl014c2542006-01-15 02:37:08 +0100906 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907}
908
909/*****************************************************************************/
910
David Howells4a561222008-07-22 11:18:43 +0100911static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800913 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 unsigned int len;
915 char *head, *tail;
916
Jiri Slabya0564e12006-12-08 02:38:37 -0800917 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800920 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100921 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800922 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100923 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925 head = portp->tx.head;
926 tail = portp->tx.tail;
927
928 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
929 len--;
930
931 if (len > 0) {
932 *head++ = ch;
933 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
934 head = portp->tx.buf;
935 }
936 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100937 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938}
939
940/*****************************************************************************/
941
942/*
943 * If there are any characters in the buffer then make sure that TX
944 * interrupts are on and get'em out. Normally used after the putchar
945 * routine has been called.
946 */
947
948static void stl_flushchars(struct tty_struct *tty)
949{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800950 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Jiri Slabya0564e12006-12-08 02:38:37 -0800952 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800955 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800957 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 return;
959
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 stl_startrxtx(portp, -1, 1);
961}
962
963/*****************************************************************************/
964
965static int stl_writeroom(struct tty_struct *tty)
966{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800967 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 char *head, *tail;
969
Jiri Slabya0564e12006-12-08 02:38:37 -0800970 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800973 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100974 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800975 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
978 head = portp->tx.head;
979 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800980 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981}
982
983/*****************************************************************************/
984
985/*
986 * Return number of chars in the TX buffer. Normally we would just
987 * calculate the number of chars in the buffer and return that, but if
988 * the buffer is empty and TX interrupts are still on then we return
989 * that the buffer still has 1 char in it. This way whoever called us
990 * will not think that ALL chars have drained - since the UART still
991 * must have some chars in it (we are busy after all).
992 */
993
994static int stl_charsinbuffer(struct tty_struct *tty)
995{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800996 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 unsigned int size;
998 char *head, *tail;
999
Jiri Slabya0564e12006-12-08 02:38:37 -08001000 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001003 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001004 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001005 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001006 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
1008 head = portp->tx.head;
1009 tail = portp->tx.tail;
1010 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1011 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1012 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001013 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
1016/*****************************************************************************/
1017
1018/*
1019 * Generate the serial struct info.
1020 */
1021
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001022static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023{
1024 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001025 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Jiri Slabya0564e12006-12-08 02:38:37 -08001027 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 memset(&sio, 0, sizeof(struct serial_struct));
Alan Coxb4eda9c2010-06-01 22:52:41 +02001030
1031 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 sio.line = portp->portnr;
1033 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001034 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 sio.baud_base = portp->baud_base;
1036 sio.close_delay = portp->close_delay;
1037 sio.closing_wait = portp->closing_wait;
1038 sio.custom_divisor = portp->custom_divisor;
1039 sio.hub6 = 0;
1040 if (portp->uartp == &stl_cd1400uart) {
1041 sio.type = PORT_CIRRUS;
1042 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1043 } else {
1044 sio.type = PORT_UNKNOWN;
1045 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1046 }
1047
1048 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001049 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 sio.irq = brdp->irq;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001051 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
1053 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1054}
1055
1056/*****************************************************************************/
1057
1058/*
1059 * Set port according to the serial struct info.
1060 * At this point we do not do any auto-configure stuff, so we will
1061 * just quietly ignore any requests to change irq, etc.
1062 */
1063
Alan Coxd18a7502008-10-13 10:40:07 +01001064static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
Alan Coxd18a7502008-10-13 10:40:07 +01001066 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 struct serial_struct sio;
1068
Jiri Slabya0564e12006-12-08 02:38:37 -08001069 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1072 return -EFAULT;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001073 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 if (!capable(CAP_SYS_ADMIN)) {
1075 if ((sio.baud_base != portp->baud_base) ||
1076 (sio.close_delay != portp->close_delay) ||
1077 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxb4eda9c2010-06-01 22:52:41 +02001078 (portp->port.flags & ~ASYNC_USR_MASK))) {
1079 mutex_unlock(&portp->port.mutex);
Jesper Juhl014c2542006-01-15 02:37:08 +01001080 return -EPERM;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001081 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083
Alan Coxf8ae4762008-07-16 21:56:37 +01001084 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 (sio.flags & ASYNC_USR_MASK);
1086 portp->baud_base = sio.baud_base;
1087 portp->close_delay = sio.close_delay;
1088 portp->closing_wait = sio.closing_wait;
1089 portp->custom_divisor = sio.custom_divisor;
Alan Coxb4eda9c2010-06-01 22:52:41 +02001090 mutex_unlock(&portp->port.mutex);
Alan Coxd18a7502008-10-13 10:40:07 +01001091 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001092 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093}
1094
1095/*****************************************************************************/
1096
Alan Cox60b33c12011-02-14 16:26:14 +00001097static int stl_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001099 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001102 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001103 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001105 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107 return stl_getsignals(portp);
1108}
1109
Alan Cox20b9d172011-02-14 16:26:50 +00001110static int stl_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 unsigned int set, unsigned int clear)
1112{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001113 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 int rts = -1, dtr = -1;
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001117 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001118 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001120 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 if (set & TIOCM_RTS)
1123 rts = 1;
1124 if (set & TIOCM_DTR)
1125 dtr = 1;
1126 if (clear & TIOCM_RTS)
1127 rts = 0;
1128 if (clear & TIOCM_DTR)
1129 dtr = 0;
1130
1131 stl_setsignals(portp, dtr, rts);
1132 return 0;
1133}
1134
Alan Cox6caa76b2011-02-14 16:27:22 +00001135static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001137 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 int rc;
1139 void __user *argp = (void __user *)arg;
1140
Alan Cox6caa76b2011-02-14 16:27:22 +00001141 pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001144 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001145 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001148 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001150 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
1152 rc = 0;
1153
1154 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 case TIOCGSERIAL:
1156 rc = stl_getserial(portp, argp);
1157 break;
1158 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001159 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 break;
1161 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001162 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 break;
1164 case COM_CLRPORTSTATS:
1165 rc = stl_clrportstats(portp, argp);
1166 break;
1167 case TIOCSERCONFIG:
1168 case TIOCSERGWILD:
1169 case TIOCSERSWILD:
1170 case TIOCSERGETLSR:
1171 case TIOCSERGSTRUCT:
1172 case TIOCSERGETMULTI:
1173 case TIOCSERSETMULTI:
1174 default:
1175 rc = -ENOIOCTLCMD;
1176 break;
1177 }
Jesper Juhl014c2542006-01-15 02:37:08 +01001178 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179}
1180
1181/*****************************************************************************/
1182
Jiri Slaby96b066b2006-12-08 02:38:42 -08001183/*
1184 * Start the transmitter again. Just turn TX interrupts back on.
1185 */
1186
1187static void stl_start(struct tty_struct *tty)
1188{
1189 struct stlport *portp;
1190
1191 pr_debug("stl_start(tty=%p)\n", tty);
1192
Jiri Slaby96b066b2006-12-08 02:38:42 -08001193 portp = tty->driver_data;
1194 if (portp == NULL)
1195 return;
1196 stl_startrxtx(portp, -1, 1);
1197}
1198
1199/*****************************************************************************/
1200
Alan Cox606d0992006-12-08 02:38:45 -08001201static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001203 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001204 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Jiri Slabya0564e12006-12-08 02:38:37 -08001206 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001209 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 return;
1211
1212 tiosp = tty->termios;
1213 if ((tiosp->c_cflag == old->c_cflag) &&
1214 (tiosp->c_iflag == old->c_iflag))
1215 return;
1216
1217 stl_setport(portp, tiosp);
1218 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1219 -1);
1220 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1221 tty->hw_stopped = 0;
1222 stl_start(tty);
1223 }
1224 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001225 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
1228/*****************************************************************************/
1229
1230/*
1231 * Attempt to flow control who ever is sending us data. Based on termios
1232 * settings use software or/and hardware flow control.
1233 */
1234
1235static void stl_throttle(struct tty_struct *tty)
1236{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001237 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
Jiri Slabya0564e12006-12-08 02:38:37 -08001239 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001242 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 return;
1244 stl_flowctrl(portp, 0);
1245}
1246
1247/*****************************************************************************/
1248
1249/*
1250 * Unflow control the device sending us data...
1251 */
1252
1253static void stl_unthrottle(struct tty_struct *tty)
1254{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001255 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
Jiri Slabya0564e12006-12-08 02:38:37 -08001257 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001260 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 return;
1262 stl_flowctrl(portp, 1);
1263}
1264
1265/*****************************************************************************/
1266
1267/*
1268 * Stop the transmitter. Basically to do this we will just turn TX
1269 * interrupts off.
1270 */
1271
1272static void stl_stop(struct tty_struct *tty)
1273{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001274 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Jiri Slabya0564e12006-12-08 02:38:37 -08001276 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001279 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return;
1281 stl_startrxtx(portp, -1, 0);
1282}
1283
1284/*****************************************************************************/
1285
1286/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 * Hangup this port. This is pretty much like closing the port, only
1288 * a little more brutal. No waiting for data to drain. Shutdown the
1289 * port and maybe drop signals.
1290 */
1291
1292static void stl_hangup(struct tty_struct *tty)
1293{
Alan Cox047e9652009-11-30 13:17:03 +00001294 struct stlport *portp = tty->driver_data;
Jiri Slabya0564e12006-12-08 02:38:37 -08001295 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
Jiri Slaby615e4a72006-12-08 02:38:38 -08001297 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return;
Alan Cox047e9652009-11-30 13:17:03 +00001299 tty_port_hangup(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300}
1301
1302/*****************************************************************************/
1303
David Howells4a561222008-07-22 11:18:43 +01001304static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001306 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Jiri Slabya0564e12006-12-08 02:38:37 -08001308 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001311 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001312 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001315 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316}
1317
1318/*****************************************************************************/
1319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320static void stl_sendxchar(struct tty_struct *tty, char ch)
1321{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001322 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Jiri Slabya0564e12006-12-08 02:38:37 -08001324 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001327 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 return;
1329
1330 if (ch == STOP_CHAR(tty))
1331 stl_sendflow(portp, 0);
1332 else if (ch == START_CHAR(tty))
1333 stl_sendflow(portp, 1);
1334 else
1335 stl_putchar(tty, ch);
1336}
1337
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001338static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001340 int sigs;
1341 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001343 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1345 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1346
1347 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001348 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001350 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001352 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001354 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
1356 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001357 sep = ' ';
1358 if (sigs & TIOCM_RTS) {
1359 seq_printf(m, "%c%s", sep, "RTS");
1360 sep = '|';
1361 }
1362 if (sigs & TIOCM_CTS) {
1363 seq_printf(m, "%c%s", sep, "CTS");
1364 sep = '|';
1365 }
1366 if (sigs & TIOCM_DTR) {
1367 seq_printf(m, "%c%s", sep, "DTR");
1368 sep = '|';
1369 }
1370 if (sigs & TIOCM_CD) {
1371 seq_printf(m, "%c%s", sep, "DCD");
1372 sep = '|';
1373 }
1374 if (sigs & TIOCM_DSR) {
1375 seq_printf(m, "%c%s", sep, "DSR");
1376 sep = '|';
1377 }
1378 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379}
1380
1381/*****************************************************************************/
1382
1383/*
1384 * Port info, read from the /proc file system.
1385 */
1386
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001387static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001389 struct stlbrd *brdp;
1390 struct stlpanel *panelp;
1391 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001392 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001393 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001397 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399/*
1400 * We scan through for each board, panel and port. The offset is
1401 * calculated on the fly, and irrelevant ports are skipped.
1402 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001403 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001405 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 continue;
1407 if (brdp->state == 0)
1408 continue;
1409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001411 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001413 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 continue;
1415
Jiri Slabyc62429d2006-12-08 02:39:14 -08001416 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 totalport++) {
1418 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001419 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001421 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 }
1423 }
1424 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001425 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426}
1427
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001428static int stl_proc_open(struct inode *inode, struct file *file)
1429{
1430 return single_open(file, stl_proc_show, NULL);
1431}
1432
1433static const struct file_operations stl_proc_fops = {
1434 .owner = THIS_MODULE,
1435 .open = stl_proc_open,
1436 .read = seq_read,
1437 .llseek = seq_lseek,
1438 .release = single_release,
1439};
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441/*****************************************************************************/
1442
1443/*
1444 * All board interrupts are vectored through here first. This code then
1445 * calls off to the approrpriate board interrupt handlers.
1446 */
1447
David Howells7d12e782006-10-05 14:55:46 +01001448static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001450 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Jeff Garzika6f97b22007-10-31 05:20:49 -04001452 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454 return IRQ_RETVAL((* brdp->isr)(brdp));
1455}
1456
1457/*****************************************************************************/
1458
1459/*
1460 * Interrupt service routine for EasyIO board types.
1461 */
1462
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001463static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 unsigned int iobase;
1467 int handled = 0;
1468
Alan Coxb65b5b52006-06-27 02:54:05 -07001469 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 panelp = brdp->panels[0];
1471 iobase = panelp->iobase;
1472 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1473 handled = 1;
1474 (* panelp->isr)(panelp, iobase);
1475 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001476 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 return handled;
1478}
1479
1480/*****************************************************************************/
1481
1482/*
1483 * Interrupt service routine for ECH-AT board types.
1484 */
1485
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001486static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001488 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001489 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 int handled = 0;
1491
1492 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1493
1494 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1495 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001496 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 ioaddr = brdp->bnkstataddr[bnknr];
1498 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1499 panelp = brdp->bnk2panel[bnknr];
1500 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1501 }
1502 }
1503 }
1504
1505 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1506
1507 return handled;
1508}
1509
1510/*****************************************************************************/
1511
1512/*
1513 * Interrupt service routine for ECH-MCA board types.
1514 */
1515
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001516static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001518 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001519 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 int handled = 0;
1521
1522 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1523 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001524 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 ioaddr = brdp->bnkstataddr[bnknr];
1526 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1527 panelp = brdp->bnk2panel[bnknr];
1528 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1529 }
1530 }
1531 }
1532 return handled;
1533}
1534
1535/*****************************************************************************/
1536
1537/*
1538 * Interrupt service routine for ECH-PCI board types.
1539 */
1540
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001541static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001543 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001544 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 int handled = 0;
1546
1547 while (1) {
1548 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001549 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1551 ioaddr = brdp->bnkstataddr[bnknr];
1552 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1553 panelp = brdp->bnk2panel[bnknr];
1554 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1555 recheck++;
1556 handled = 1;
1557 }
1558 }
1559 if (! recheck)
1560 break;
1561 }
1562 return handled;
1563}
1564
1565/*****************************************************************************/
1566
1567/*
1568 * Interrupt service routine for ECH-8/64-PCI board types.
1569 */
1570
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001571static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001573 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001574 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 int handled = 0;
1576
1577 while (inb(brdp->ioctrl) & 0x1) {
1578 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001579 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 ioaddr = brdp->bnkstataddr[bnknr];
1581 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1582 panelp = brdp->bnk2panel[bnknr];
1583 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1584 }
1585 }
1586 }
1587
1588 return handled;
1589}
1590
1591/*****************************************************************************/
1592
1593/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 * Initialize all the ports on a panel.
1595 */
1596
Jiri Slaby705c1862006-12-08 02:39:11 -08001597static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001599 struct stlport *portp;
1600 unsigned int i;
1601 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Jiri Slabya0564e12006-12-08 02:38:37 -08001603 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605 chipmask = stl_panelinit(brdp, panelp);
1606
1607/*
1608 * All UART's are initialized (if found!). Now go through and setup
1609 * each ports data structures.
1610 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001611 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001612 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001613 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001615 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 break;
1617 }
Alan Coxd18a7502008-10-13 10:40:07 +01001618 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001619 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 portp->magic = STL_PORTMAGIC;
1621 portp->portnr = i;
1622 portp->brdnr = panelp->brdnr;
1623 portp->panelnr = panelp->panelnr;
1624 portp->uartp = panelp->uartp;
1625 portp->clk = brdp->clk;
1626 portp->baud_base = STL_BAUDBASE;
1627 portp->close_delay = STL_CLOSEDELAY;
1628 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001629 init_waitqueue_head(&portp->port.open_wait);
1630 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 portp->stats.brd = portp->brdnr;
1632 portp->stats.panel = portp->panelnr;
1633 portp->stats.port = portp->portnr;
1634 panelp->ports[i] = portp;
1635 stl_portinit(brdp, panelp, portp);
1636 }
1637
Jiri Slabyc62429d2006-12-08 02:39:14 -08001638 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639}
1640
Jiri Slaby3b85b342006-12-08 02:39:10 -08001641static void stl_cleanup_panels(struct stlbrd *brdp)
1642{
1643 struct stlpanel *panelp;
1644 struct stlport *portp;
1645 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001646 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001647
1648 for (j = 0; j < STL_MAXPANELS; j++) {
1649 panelp = brdp->panels[j];
1650 if (panelp == NULL)
1651 continue;
1652 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1653 portp = panelp->ports[k];
1654 if (portp == NULL)
1655 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001656 tty = tty_port_tty_get(&portp->port);
1657 if (tty != NULL) {
1658 stl_hangup(tty);
1659 tty_kref_put(tty);
1660 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001661 kfree(portp->tx.buf);
1662 kfree(portp);
1663 }
1664 kfree(panelp);
1665 }
1666}
1667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668/*****************************************************************************/
1669
1670/*
1671 * Try to find and initialize an EasyIO board.
1672 */
1673
Jiri Slaby705c1862006-12-08 02:39:11 -08001674static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001676 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 unsigned int status;
1678 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001679 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
Jiri Slabya0564e12006-12-08 02:38:37 -08001681 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
1683 brdp->ioctrl = brdp->ioaddr1 + 1;
1684 brdp->iostatus = brdp->ioaddr1 + 2;
1685
1686 status = inb(brdp->iostatus);
1687 if ((status & EIO_IDBITMASK) == EIO_MK3)
1688 brdp->ioctrl++;
1689
1690/*
1691 * Handle board specific stuff now. The real difference is PCI
1692 * or not PCI.
1693 */
1694 if (brdp->brdtype == BRD_EASYIOPCI) {
1695 brdp->iosize1 = 0x80;
1696 brdp->iosize2 = 0x80;
1697 name = "serial(EIO-PCI)";
1698 outb(0x41, (brdp->ioaddr2 + 0x4c));
1699 } else {
1700 brdp->iosize1 = 8;
1701 name = "serial(EIO)";
1702 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1703 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1704 printk("STALLION: invalid irq=%d for brd=%d\n",
1705 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001706 retval = -EINVAL;
1707 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 }
1709 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1710 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1711 brdp->ioctrl);
1712 }
1713
Jiri Slaby3b85b342006-12-08 02:39:10 -08001714 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1716 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1717 "%x conflicts with another device\n", brdp->brdnr,
1718 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001719 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 }
1721
1722 if (brdp->iosize2 > 0)
1723 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1724 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1725 "address %x conflicts with another device\n",
1726 brdp->brdnr, brdp->ioaddr2);
1727 printk(KERN_WARNING "STALLION: Warning, also "
1728 "releasing board %d I/O address %x \n",
1729 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001730 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 }
1732
1733/*
1734 * Everything looks OK, so let's go ahead and probe for the hardware.
1735 */
1736 brdp->clk = CD1400_CLK;
1737 brdp->isr = stl_eiointr;
1738
Jiri Slaby3b85b342006-12-08 02:39:10 -08001739 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 switch (status & EIO_IDBITMASK) {
1741 case EIO_8PORTM:
1742 brdp->clk = CD1400_CLK8M;
1743 /* fall thru */
1744 case EIO_8PORTRS:
1745 case EIO_8PORTDI:
1746 brdp->nrports = 8;
1747 break;
1748 case EIO_4PORTRS:
1749 brdp->nrports = 4;
1750 break;
1751 case EIO_MK3:
1752 switch (status & EIO_BRDMASK) {
1753 case ID_BRD4:
1754 brdp->nrports = 4;
1755 break;
1756 case ID_BRD8:
1757 brdp->nrports = 8;
1758 break;
1759 case ID_BRD16:
1760 brdp->nrports = 16;
1761 break;
1762 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001763 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 }
1765 break;
1766 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001767 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 }
1769
1770/*
1771 * We have verified that the board is actually present, so now we
1772 * can complete the setup.
1773 */
1774
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001775 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001776 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001778 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001779 retval = -ENOMEM;
1780 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 panelp->magic = STL_PANELMAGIC;
1784 panelp->brdnr = brdp->brdnr;
1785 panelp->panelnr = 0;
1786 panelp->nrports = brdp->nrports;
1787 panelp->iobase = brdp->ioaddr1;
1788 panelp->hwid = status;
1789 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001790 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 panelp->isr = stl_sc26198intr;
1792 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001793 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 panelp->isr = stl_cd1400eiointr;
1795 }
1796
1797 brdp->panels[0] = panelp;
1798 brdp->nrpanels = 1;
1799 brdp->state |= BRD_FOUND;
1800 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001801 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 printk("STALLION: failed to register interrupt "
1803 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001804 retval = -ENODEV;
1805 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001807
1808 return 0;
1809err_fr:
1810 stl_cleanup_panels(brdp);
1811err_rel2:
1812 if (brdp->iosize2 > 0)
1813 release_region(brdp->ioaddr2, brdp->iosize2);
1814err_rel1:
1815 release_region(brdp->ioaddr1, brdp->iosize1);
1816err:
1817 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818}
1819
1820/*****************************************************************************/
1821
1822/*
1823 * Try to find an ECH board and initialize it. This code is capable of
1824 * dealing with all types of ECH board.
1825 */
1826
Jiri Slaby705c1862006-12-08 02:39:11 -08001827static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001829 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001830 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1831 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 char *name;
1833
Jiri Slabya0564e12006-12-08 02:38:37 -08001834 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835
1836 status = 0;
1837 conflict = 0;
1838
1839/*
1840 * Set up the initial board register contents for boards. This varies a
1841 * bit between the different board types. So we need to handle each
1842 * separately. Also do a check that the supplied IRQ is good.
1843 */
1844 switch (brdp->brdtype) {
1845
1846 case BRD_ECH:
1847 brdp->isr = stl_echatintr;
1848 brdp->ioctrl = brdp->ioaddr1 + 1;
1849 brdp->iostatus = brdp->ioaddr1 + 1;
1850 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001851 if ((status & ECH_IDBITMASK) != ECH_ID) {
1852 retval = -ENODEV;
1853 goto err;
1854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1856 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1857 printk("STALLION: invalid irq=%d for brd=%d\n",
1858 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001859 retval = -EINVAL;
1860 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 }
1862 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1863 status |= (stl_vecmap[brdp->irq] << 1);
1864 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1865 brdp->ioctrlval = ECH_INTENABLE |
1866 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001867 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1869 brdp->iosize1 = 2;
1870 brdp->iosize2 = 32;
1871 name = "serial(EC8/32)";
1872 outb(status, brdp->ioaddr1);
1873 break;
1874
1875 case BRD_ECHMC:
1876 brdp->isr = stl_echmcaintr;
1877 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1878 brdp->iostatus = brdp->ioctrl;
1879 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001880 if ((status & ECH_IDBITMASK) != ECH_ID) {
1881 retval = -ENODEV;
1882 goto err;
1883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1885 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1886 printk("STALLION: invalid irq=%d for brd=%d\n",
1887 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001888 retval = -EINVAL;
1889 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 }
1891 outb(ECHMC_BRDRESET, brdp->ioctrl);
1892 outb(ECHMC_INTENABLE, brdp->ioctrl);
1893 brdp->iosize1 = 64;
1894 name = "serial(EC8/32-MC)";
1895 break;
1896
1897 case BRD_ECHPCI:
1898 brdp->isr = stl_echpciintr;
1899 brdp->ioctrl = brdp->ioaddr1 + 2;
1900 brdp->iosize1 = 4;
1901 brdp->iosize2 = 8;
1902 name = "serial(EC8/32-PCI)";
1903 break;
1904
1905 case BRD_ECH64PCI:
1906 brdp->isr = stl_echpci64intr;
1907 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1908 outb(0x43, (brdp->ioaddr1 + 0x4c));
1909 brdp->iosize1 = 0x80;
1910 brdp->iosize2 = 0x80;
1911 name = "serial(EC8/64-PCI)";
1912 break;
1913
1914 default:
1915 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001916 retval = -EINVAL;
1917 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 }
1919
1920/*
1921 * Check boards for possible IO address conflicts and return fail status
1922 * if an IO conflict found.
1923 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001924 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1926 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1927 "%x conflicts with another device\n", brdp->brdnr,
1928 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001929 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 }
1931
1932 if (brdp->iosize2 > 0)
1933 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1934 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1935 "address %x conflicts with another device\n",
1936 brdp->brdnr, brdp->ioaddr2);
1937 printk(KERN_WARNING "STALLION: Warning, also "
1938 "releasing board %d I/O address %x \n",
1939 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001940 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 }
1942
1943/*
1944 * Scan through the secondary io address space looking for panels.
1945 * As we find'em allocate and initialize panel structures for each.
1946 */
1947 brdp->clk = CD1400_CLK;
1948 brdp->hwid = status;
1949
1950 ioaddr = brdp->ioaddr2;
1951 banknr = 0;
1952 panelnr = 0;
1953 nxtid = 0;
1954
Jiri Slabyc62429d2006-12-08 02:39:14 -08001955 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 if (brdp->brdtype == BRD_ECHPCI) {
1957 outb(nxtid, brdp->ioctrl);
1958 ioaddr = brdp->ioaddr2;
1959 }
1960 status = inb(ioaddr + ECH_PNLSTATUS);
1961 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07001962 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001963 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001964 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001966 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07001967 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001968 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 panelp->magic = STL_PANELMAGIC;
1971 panelp->brdnr = brdp->brdnr;
1972 panelp->panelnr = panelnr;
1973 panelp->iobase = ioaddr;
1974 panelp->pagenr = nxtid;
1975 panelp->hwid = status;
1976 brdp->bnk2panel[banknr] = panelp;
1977 brdp->bnkpageaddr[banknr] = nxtid;
1978 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
1979
1980 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001981 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 panelp->isr = stl_sc26198intr;
1983 if (status & ECH_PNL16PORT) {
1984 panelp->nrports = 16;
1985 brdp->bnk2panel[banknr] = panelp;
1986 brdp->bnkpageaddr[banknr] = nxtid;
1987 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
1988 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001989 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001992 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 panelp->isr = stl_cd1400echintr;
1994 if (status & ECH_PNL16PORT) {
1995 panelp->nrports = 16;
1996 panelp->ackmask = 0x80;
1997 if (brdp->brdtype != BRD_ECHPCI)
1998 ioaddr += EREG_BANKSIZE;
1999 brdp->bnk2panel[banknr] = panelp;
2000 brdp->bnkpageaddr[banknr] = ++nxtid;
2001 brdp->bnkstataddr[banknr++] = ioaddr +
2002 ECH_PNLSTATUS;
2003 } else {
2004 panelp->nrports = 8;
2005 panelp->ackmask = 0xc0;
2006 }
2007 }
2008
2009 nxtid++;
2010 ioaddr += EREG_BANKSIZE;
2011 brdp->nrports += panelp->nrports;
2012 brdp->panels[panelnr++] = panelp;
2013 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002014 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2015 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002016 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 }
2019
2020 brdp->nrpanels = panelnr;
2021 brdp->nrbnks = banknr;
2022 if (brdp->brdtype == BRD_ECH)
2023 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2024
2025 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002026 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 printk("STALLION: failed to register interrupt "
2028 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002029 retval = -ENODEV;
2030 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
2032
Jiri Slaby3b85b342006-12-08 02:39:10 -08002033 return 0;
2034err_fr:
2035 stl_cleanup_panels(brdp);
2036 if (brdp->iosize2 > 0)
2037 release_region(brdp->ioaddr2, brdp->iosize2);
2038err_rel1:
2039 release_region(brdp->ioaddr1, brdp->iosize1);
2040err:
2041 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042}
2043
2044/*****************************************************************************/
2045
2046/*
2047 * Initialize and configure the specified board.
2048 * Scan through all the boards in the configuration and see what we
2049 * can find. Handle EIO and the ECH boards a little differently here
2050 * since the initial search and setup is very different.
2051 */
2052
Jiri Slaby705c1862006-12-08 02:39:11 -08002053static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002055 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Jiri Slabya0564e12006-12-08 02:38:37 -08002057 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
2059 switch (brdp->brdtype) {
2060 case BRD_EASYIO:
2061 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002062 retval = stl_initeio(brdp);
2063 if (retval)
2064 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 break;
2066 case BRD_ECH:
2067 case BRD_ECHMC:
2068 case BRD_ECHPCI:
2069 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002070 retval = stl_initech(brdp);
2071 if (retval)
2072 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 break;
2074 default:
2075 printk("STALLION: board=%d is unknown board type=%d\n",
2076 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002077 retval = -ENODEV;
2078 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 }
2080
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 if ((brdp->state & BRD_FOUND) == 0) {
2082 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2083 stl_brdnames[brdp->brdtype], brdp->brdnr,
2084 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002085 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 }
2087
Jiri Slabyc62429d2006-12-08 02:39:14 -08002088 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002089 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 stl_initports(brdp, brdp->panels[i]);
2091
2092 printk("STALLION: %s found, board=%d io=%x irq=%d "
2093 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2094 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2095 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002096
2097 return 0;
2098err_free:
2099 free_irq(brdp->irq, brdp);
2100
2101 stl_cleanup_panels(brdp);
2102
2103 release_region(brdp->ioaddr1, brdp->iosize1);
2104 if (brdp->iosize2 > 0)
2105 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002106err:
2107 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108}
2109
2110/*****************************************************************************/
2111
2112/*
2113 * Find the next available board number that is free.
2114 */
2115
Jiri Slaby705c1862006-12-08 02:39:11 -08002116static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002118 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119
Jiri Slabyc62429d2006-12-08 02:39:14 -08002120 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002121 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 if (i >= stl_nrbrds)
2123 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002124 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002126
2127 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128}
2129
2130/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131/*
2132 * We have a Stallion board. Allocate a board structure and
2133 * initialize it. Read its IO and IRQ resources from PCI
2134 * configuration space.
2135 */
2136
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002137static int __devinit stl_pciprobe(struct pci_dev *pdev,
2138 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002140 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002141 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002142 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002144 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002145 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002146
Jiri Slaby3b85b342006-12-08 02:39:10 -08002147 retval = pci_enable_device(pdev);
2148 if (retval)
2149 goto err;
2150 brdp = stl_allocbrd();
2151 if (brdp == NULL) {
2152 retval = -ENOMEM;
2153 goto err;
2154 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002155 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002156 brdnr = stl_getbrdnr();
2157 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002158 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002160 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002161 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002162 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002164 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002165 stl_brds[brdp->brdnr] = brdp;
2166 mutex_unlock(&stl_brdslock);
2167
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002169 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170
2171/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 * We have all resources from the board, so let's setup the actual
2173 * board structure now.
2174 */
2175 switch (brdtype) {
2176 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002177 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2178 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 break;
2180 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002181 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2182 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 break;
2184 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002185 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2186 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 break;
2188 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002189 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 break;
2191 }
2192
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002193 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002194 retval = stl_brdinit(brdp);
2195 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002196 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002198 pci_set_drvdata(pdev, brdp);
2199
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002200 for (i = 0; i < brdp->nrports; i++)
2201 tty_register_device(stl_serial,
2202 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2203
Jiri Slaby3b85b342006-12-08 02:39:10 -08002204 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002205err_null:
2206 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002207err_fr:
2208 kfree(brdp);
2209err:
2210 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211}
2212
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002213static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002215 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002216 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002218 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002220 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002222 release_region(brdp->ioaddr1, brdp->iosize1);
2223 if (brdp->iosize2 > 0)
2224 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002226 for (i = 0; i < brdp->nrports; i++)
2227 tty_unregister_device(stl_serial,
2228 brdp->brdnr * STL_MAXPORTS + i);
2229
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002230 stl_brds[brdp->brdnr] = NULL;
2231 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232}
2233
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002234static struct pci_driver stl_pcidriver = {
2235 .name = "stallion",
2236 .id_table = stl_pcibrds,
2237 .probe = stl_pciprobe,
2238 .remove = __devexit_p(stl_pciremove)
2239};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241/*****************************************************************************/
2242
2243/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 * Return the board stats structure to user app.
2245 */
2246
2247static int stl_getbrdstats(combrd_t __user *bp)
2248{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002249 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002250 struct stlbrd *brdp;
2251 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002252 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
2254 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2255 return -EFAULT;
2256 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002257 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002259 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002260 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
2262 memset(&stl_brdstats, 0, sizeof(combrd_t));
2263 stl_brdstats.brd = brdp->brdnr;
2264 stl_brdstats.type = brdp->brdtype;
2265 stl_brdstats.hwid = brdp->hwid;
2266 stl_brdstats.state = brdp->state;
2267 stl_brdstats.ioaddr = brdp->ioaddr1;
2268 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2269 stl_brdstats.irq = brdp->irq;
2270 stl_brdstats.nrpanels = brdp->nrpanels;
2271 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002272 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 panelp = brdp->panels[i];
2274 stl_brdstats.panels[i].panel = i;
2275 stl_brdstats.panels[i].hwid = panelp->hwid;
2276 stl_brdstats.panels[i].nrports = panelp->nrports;
2277 }
2278
2279 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2280}
2281
2282/*****************************************************************************/
2283
2284/*
2285 * Resolve the referenced port number into a port struct pointer.
2286 */
2287
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002288static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002290 struct stlbrd *brdp;
2291 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Jiri Slabyc62429d2006-12-08 02:39:14 -08002293 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2294 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002296 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002297 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002298 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002299 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002301 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002302 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002303 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002304 return NULL;
2305 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306}
2307
2308/*****************************************************************************/
2309
2310/*
2311 * Return the port stats structure to user app. A NULL port struct
2312 * pointer passed in means that we need to find out from the app
2313 * what port to get stats for (used through board control device).
2314 */
2315
Alan Coxd18a7502008-10-13 10:40:07 +01002316static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002318 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 unsigned char *head, *tail;
2320 unsigned long flags;
2321
2322 if (!portp) {
2323 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2324 return -EFAULT;
2325 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2326 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002327 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002328 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 }
2330
Alan Coxb4eda9c2010-06-01 22:52:41 +02002331 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002333 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 portp->stats.hwid = portp->hwid;
2335
2336 portp->stats.ttystate = 0;
2337 portp->stats.cflags = 0;
2338 portp->stats.iflags = 0;
2339 portp->stats.oflags = 0;
2340 portp->stats.lflags = 0;
2341 portp->stats.rxbuffered = 0;
2342
Alan Coxb65b5b52006-06-27 02:54:05 -07002343 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002344 if (tty != NULL && portp->port.tty == tty) {
2345 portp->stats.ttystate = tty->flags;
2346 /* No longer available as a statistic */
2347 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2348 if (tty->termios != NULL) {
2349 portp->stats.cflags = tty->termios->c_cflag;
2350 portp->stats.iflags = tty->termios->c_iflag;
2351 portp->stats.oflags = tty->termios->c_oflag;
2352 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 }
Alan Coxd18a7502008-10-13 10:40:07 +01002354 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002355 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
2357 head = portp->tx.head;
2358 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002359 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2360 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
2362 portp->stats.signals = (unsigned long) stl_getsignals(portp);
Alan Coxb4eda9c2010-06-01 22:52:41 +02002363 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364
2365 return copy_to_user(cp, &portp->stats,
2366 sizeof(comstats_t)) ? -EFAULT : 0;
2367}
2368
2369/*****************************************************************************/
2370
2371/*
2372 * Clear the port stats structure. We also return it zeroed out...
2373 */
2374
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002375static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002377 comstats_t stl_comstats;
2378
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 if (!portp) {
2380 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2381 return -EFAULT;
2382 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2383 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002384 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002385 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 }
2387
Alan Coxb4eda9c2010-06-01 22:52:41 +02002388 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 memset(&portp->stats, 0, sizeof(comstats_t));
2390 portp->stats.brd = portp->brdnr;
2391 portp->stats.panel = portp->panelnr;
2392 portp->stats.port = portp->portnr;
Alan Coxb4eda9c2010-06-01 22:52:41 +02002393 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 return copy_to_user(cp, &portp->stats,
2395 sizeof(comstats_t)) ? -EFAULT : 0;
2396}
2397
2398/*****************************************************************************/
2399
2400/*
2401 * Return the entire driver ports structure to a user app.
2402 */
2403
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002404static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002406 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002407 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002409 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 return -EFAULT;
2411 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2412 stl_dummyport.portnr);
2413 if (!portp)
2414 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002415 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416}
2417
2418/*****************************************************************************/
2419
2420/*
2421 * Return the entire driver board structure to a user app.
2422 */
2423
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002424static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002426 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002427 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002429 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002431 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 return -ENODEV;
2433 brdp = stl_brds[stl_dummybrd.brdnr];
2434 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002435 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002436 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437}
2438
2439/*****************************************************************************/
2440
2441/*
2442 * The "staliomem" device is also required to do some special operations
2443 * on the board and/or ports. In this driver it is mostly used for stats
2444 * collection.
2445 */
2446
Alan Cox894cb912009-10-13 16:34:15 +01002447static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448{
2449 int brdnr, rc;
2450 void __user *argp = (void __user *)arg;
2451
Alan Cox894cb912009-10-13 16:34:15 +01002452 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
Alan Cox894cb912009-10-13 16:34:15 +01002454 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002456 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 rc = 0;
2458
2459 switch (cmd) {
2460 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002461 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 break;
2463 case COM_CLRPORTSTATS:
2464 rc = stl_clrportstats(NULL, argp);
2465 break;
2466 case COM_GETBRDSTATS:
2467 rc = stl_getbrdstats(argp);
2468 break;
2469 case COM_READPORT:
2470 rc = stl_getportstruct(argp);
2471 break;
2472 case COM_READBOARD:
2473 rc = stl_getbrdstruct(argp);
2474 break;
2475 default:
2476 rc = -ENOIOCTLCMD;
2477 break;
2478 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002479 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480}
2481
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002482static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 .open = stl_open,
2484 .close = stl_close,
2485 .write = stl_write,
2486 .put_char = stl_putchar,
2487 .flush_chars = stl_flushchars,
2488 .write_room = stl_writeroom,
2489 .chars_in_buffer = stl_charsinbuffer,
2490 .ioctl = stl_ioctl,
2491 .set_termios = stl_settermios,
2492 .throttle = stl_throttle,
2493 .unthrottle = stl_unthrottle,
2494 .stop = stl_stop,
2495 .start = stl_start,
2496 .hangup = stl_hangup,
2497 .flush_buffer = stl_flushbuffer,
2498 .break_ctl = stl_breakctl,
2499 .wait_until_sent = stl_waituntilsent,
2500 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 .tiocmget = stl_tiocmget,
2502 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002503 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504};
2505
Alan Cox31f35932009-01-02 13:45:05 +00002506static const struct tty_port_operations stl_port_ops = {
2507 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002508 .dtr_rts = stl_dtr_rts,
Alan Cox047e9652009-11-30 13:17:03 +00002509 .activate = stl_activate,
2510 .shutdown = stl_shutdown,
Alan Cox31f35932009-01-02 13:45:05 +00002511};
2512
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514/* CD1400 HARDWARE FUNCTIONS */
2515/*****************************************************************************/
2516
2517/*
2518 * These functions get/set/update the registers of the cd1400 UARTs.
2519 * Access to the cd1400 registers is via an address/data io port pair.
2520 * (Maybe should make this inline...)
2521 */
2522
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002523static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524{
2525 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002526 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527}
2528
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002529static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002531 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 outb(value, portp->ioaddr + EREG_DATA);
2533}
2534
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002535static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002537 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 if (inb(portp->ioaddr + EREG_DATA) != value) {
2539 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002540 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002542 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543}
2544
2545/*****************************************************************************/
2546
2547/*
2548 * Inbitialize the UARTs in a panel. We don't care what sort of board
2549 * these ports are on - since the port io registers are almost
2550 * identical when dealing with ports.
2551 */
2552
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002553static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554{
2555 unsigned int gfrcr;
2556 int chipmask, i, j;
2557 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002558 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Jiri Slabya0564e12006-12-08 02:38:37 -08002560 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Alan Coxb65b5b52006-06-27 02:54:05 -07002562 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 BRDENABLE(panelp->brdnr, panelp->pagenr);
2564
2565/*
2566 * Check that each chip is present and started up OK.
2567 */
2568 chipmask = 0;
2569 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002570 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 if (brdp->brdtype == BRD_ECHPCI) {
2572 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2573 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002574 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 uartaddr = (i & 0x01) ? 0x080 : 0;
2577 outb((GFRCR + uartaddr), ioaddr);
2578 outb(0, (ioaddr + EREG_DATA));
2579 outb((CCR + uartaddr), ioaddr);
2580 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2581 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2582 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002583 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2585 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002586
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2588 printk("STALLION: cd1400 not responding, "
2589 "brd=%d panel=%d chip=%d\n",
2590 panelp->brdnr, panelp->panelnr, i);
2591 continue;
2592 }
2593 chipmask |= (0x1 << i);
2594 outb((PPR + uartaddr), ioaddr);
2595 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2596 }
2597
2598 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002599 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002600 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601}
2602
2603/*****************************************************************************/
2604
2605/*
2606 * Initialize hardware specific port registers.
2607 */
2608
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002609static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610{
Alan Coxb65b5b52006-06-27 02:54:05 -07002611 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002612 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2613 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Jiri Slaby615e4a72006-12-08 02:38:38 -08002615 if ((brdp == NULL) || (panelp == NULL) ||
2616 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 return;
2618
Alan Coxb65b5b52006-06-27 02:54:05 -07002619 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2621 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2622 portp->uartaddr = (portp->portnr & 0x04) << 5;
2623 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2624
2625 BRDENABLE(portp->brdnr, portp->pagenr);
2626 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2627 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2628 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2629 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002630 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631}
2632
2633/*****************************************************************************/
2634
2635/*
2636 * Wait for the command register to be ready. We will poll this,
2637 * since it won't usually take too long to be ready.
2638 */
2639
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002640static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641{
2642 int i;
2643
Jiri Slabyc62429d2006-12-08 02:39:14 -08002644 for (i = 0; i < CCR_MAXWAIT; i++)
2645 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
2648 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2649 portp->portnr, portp->panelnr, portp->brdnr);
2650}
2651
2652/*****************************************************************************/
2653
2654/*
2655 * Set up the cd1400 registers for a port based on the termios port
2656 * settings.
2657 */
2658
Alan Cox606d0992006-12-08 02:38:45 -08002659static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002661 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 unsigned long flags;
2663 unsigned int clkdiv, baudrate;
2664 unsigned char cor1, cor2, cor3;
2665 unsigned char cor4, cor5, ccr;
2666 unsigned char srer, sreron, sreroff;
2667 unsigned char mcor1, mcor2, rtpr;
2668 unsigned char clk, div;
2669
2670 cor1 = 0;
2671 cor2 = 0;
2672 cor3 = 0;
2673 cor4 = 0;
2674 cor5 = 0;
2675 ccr = 0;
2676 rtpr = 0;
2677 clk = 0;
2678 div = 0;
2679 mcor1 = 0;
2680 mcor2 = 0;
2681 sreron = 0;
2682 sreroff = 0;
2683
2684 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002685 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 return;
2687
2688/*
2689 * Set up the RX char ignore mask with those RX error types we
2690 * can ignore. We can get the cd1400 to help us out a little here,
2691 * it will ignore parity errors and breaks for us.
2692 */
2693 portp->rxignoremsk = 0;
2694 if (tiosp->c_iflag & IGNPAR) {
2695 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2696 cor1 |= COR1_PARIGNORE;
2697 }
2698 if (tiosp->c_iflag & IGNBRK) {
2699 portp->rxignoremsk |= ST_BREAK;
2700 cor4 |= COR4_IGNBRK;
2701 }
2702
2703 portp->rxmarkmsk = ST_OVERRUN;
2704 if (tiosp->c_iflag & (INPCK | PARMRK))
2705 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2706 if (tiosp->c_iflag & BRKINT)
2707 portp->rxmarkmsk |= ST_BREAK;
2708
2709/*
2710 * Go through the char size, parity and stop bits and set all the
2711 * option register appropriately.
2712 */
2713 switch (tiosp->c_cflag & CSIZE) {
2714 case CS5:
2715 cor1 |= COR1_CHL5;
2716 break;
2717 case CS6:
2718 cor1 |= COR1_CHL6;
2719 break;
2720 case CS7:
2721 cor1 |= COR1_CHL7;
2722 break;
2723 default:
2724 cor1 |= COR1_CHL8;
2725 break;
2726 }
2727
2728 if (tiosp->c_cflag & CSTOPB)
2729 cor1 |= COR1_STOP2;
2730 else
2731 cor1 |= COR1_STOP1;
2732
2733 if (tiosp->c_cflag & PARENB) {
2734 if (tiosp->c_cflag & PARODD)
2735 cor1 |= (COR1_PARENB | COR1_PARODD);
2736 else
2737 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2738 } else {
2739 cor1 |= COR1_PARNONE;
2740 }
2741
2742/*
2743 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2744 * space for hardware flow control and the like. This should be set to
2745 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2746 * really be based on VTIME.
2747 */
2748 cor3 |= FIFO_RXTHRESHOLD;
2749 rtpr = 2;
2750
2751/*
2752 * Calculate the baud rate timers. For now we will just assume that
2753 * the input and output baud are the same. Could have used a baud
2754 * table here, but this way we can generate virtually any baud rate
2755 * we like!
2756 */
2757 baudrate = tiosp->c_cflag & CBAUD;
2758 if (baudrate & CBAUDEX) {
2759 baudrate &= ~CBAUDEX;
2760 if ((baudrate < 1) || (baudrate > 4))
2761 tiosp->c_cflag &= ~CBAUDEX;
2762 else
2763 baudrate += 15;
2764 }
2765 baudrate = stl_baudrates[baudrate];
2766 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002767 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002769 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002771 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002773 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002775 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 baudrate = (portp->baud_base / portp->custom_divisor);
2777 }
2778 if (baudrate > STL_CD1400MAXBAUD)
2779 baudrate = STL_CD1400MAXBAUD;
2780
2781 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002782 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2783 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 if (clkdiv < 0x100)
2785 break;
2786 }
2787 div = (unsigned char) clkdiv;
2788 }
2789
2790/*
2791 * Check what form of modem signaling is required and set it up.
2792 */
2793 if ((tiosp->c_cflag & CLOCAL) == 0) {
2794 mcor1 |= MCOR1_DCD;
2795 mcor2 |= MCOR2_DCD;
2796 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002797 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002798 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002799 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800
2801/*
2802 * Setup cd1400 enhanced modes if we can. In particular we want to
2803 * handle as much of the flow control as possible automatically. As
2804 * well as saving a few CPU cycles it will also greatly improve flow
2805 * control reliability.
2806 */
2807 if (tiosp->c_iflag & IXON) {
2808 cor2 |= COR2_TXIBE;
2809 cor3 |= COR3_SCD12;
2810 if (tiosp->c_iflag & IXANY)
2811 cor2 |= COR2_IXM;
2812 }
2813
2814 if (tiosp->c_cflag & CRTSCTS) {
2815 cor2 |= COR2_CTSAE;
2816 mcor1 |= FIFO_RTSTHRESHOLD;
2817 }
2818
2819/*
2820 * All cd1400 register values calculated so go through and set
2821 * them all up.
2822 */
2823
Jiri Slabya0564e12006-12-08 02:38:37 -08002824 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002826 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002828 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002830 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2831 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2833 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
Alan Coxb65b5b52006-06-27 02:54:05 -07002835 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 BRDENABLE(portp->brdnr, portp->pagenr);
2837 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2838 srer = stl_cd1400getreg(portp, SRER);
2839 stl_cd1400setreg(portp, SRER, 0);
2840 if (stl_cd1400updatereg(portp, COR1, cor1))
2841 ccr = 1;
2842 if (stl_cd1400updatereg(portp, COR2, cor2))
2843 ccr = 1;
2844 if (stl_cd1400updatereg(portp, COR3, cor3))
2845 ccr = 1;
2846 if (ccr) {
2847 stl_cd1400ccrwait(portp);
2848 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2849 }
2850 stl_cd1400setreg(portp, COR4, cor4);
2851 stl_cd1400setreg(portp, COR5, cor5);
2852 stl_cd1400setreg(portp, MCOR1, mcor1);
2853 stl_cd1400setreg(portp, MCOR2, mcor2);
2854 if (baudrate > 0) {
2855 stl_cd1400setreg(portp, TCOR, clk);
2856 stl_cd1400setreg(portp, TBPR, div);
2857 stl_cd1400setreg(portp, RCOR, clk);
2858 stl_cd1400setreg(portp, RBPR, div);
2859 }
2860 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2861 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2862 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2863 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2864 stl_cd1400setreg(portp, RTPR, rtpr);
2865 mcor1 = stl_cd1400getreg(portp, MSVR1);
2866 if (mcor1 & MSVR1_DCD)
2867 portp->sigs |= TIOCM_CD;
2868 else
2869 portp->sigs &= ~TIOCM_CD;
2870 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2871 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002872 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873}
2874
2875/*****************************************************************************/
2876
2877/*
2878 * Set the state of the DTR and RTS signals.
2879 */
2880
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002881static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882{
2883 unsigned char msvr1, msvr2;
2884 unsigned long flags;
2885
Jiri Slabya0564e12006-12-08 02:38:37 -08002886 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2887 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
2889 msvr1 = 0;
2890 msvr2 = 0;
2891 if (dtr > 0)
2892 msvr1 = MSVR1_DTR;
2893 if (rts > 0)
2894 msvr2 = MSVR2_RTS;
2895
Alan Coxb65b5b52006-06-27 02:54:05 -07002896 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 BRDENABLE(portp->brdnr, portp->pagenr);
2898 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2899 if (rts >= 0)
2900 stl_cd1400setreg(portp, MSVR2, msvr2);
2901 if (dtr >= 0)
2902 stl_cd1400setreg(portp, MSVR1, msvr1);
2903 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002904 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905}
2906
2907/*****************************************************************************/
2908
2909/*
2910 * Return the state of the signals.
2911 */
2912
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002913static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914{
2915 unsigned char msvr1, msvr2;
2916 unsigned long flags;
2917 int sigs;
2918
Jiri Slabya0564e12006-12-08 02:38:37 -08002919 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920
Alan Coxb65b5b52006-06-27 02:54:05 -07002921 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 BRDENABLE(portp->brdnr, portp->pagenr);
2923 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2924 msvr1 = stl_cd1400getreg(portp, MSVR1);
2925 msvr2 = stl_cd1400getreg(portp, MSVR2);
2926 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002927 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928
2929 sigs = 0;
2930 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2931 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2932 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2933 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2934#if 0
2935 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2936 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2937#else
2938 sigs |= TIOCM_DSR;
2939#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002940 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941}
2942
2943/*****************************************************************************/
2944
2945/*
2946 * Enable/Disable the Transmitter and/or Receiver.
2947 */
2948
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002949static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950{
2951 unsigned char ccr;
2952 unsigned long flags;
2953
Jiri Slabya0564e12006-12-08 02:38:37 -08002954 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2955
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956 ccr = 0;
2957
2958 if (tx == 0)
2959 ccr |= CCR_TXDISABLE;
2960 else if (tx > 0)
2961 ccr |= CCR_TXENABLE;
2962 if (rx == 0)
2963 ccr |= CCR_RXDISABLE;
2964 else if (rx > 0)
2965 ccr |= CCR_RXENABLE;
2966
Alan Coxb65b5b52006-06-27 02:54:05 -07002967 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 BRDENABLE(portp->brdnr, portp->pagenr);
2969 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2970 stl_cd1400ccrwait(portp);
2971 stl_cd1400setreg(portp, CCR, ccr);
2972 stl_cd1400ccrwait(portp);
2973 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002974 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975}
2976
2977/*****************************************************************************/
2978
2979/*
2980 * Start/stop the Transmitter and/or Receiver.
2981 */
2982
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002983static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984{
2985 unsigned char sreron, sreroff;
2986 unsigned long flags;
2987
Jiri Slabya0564e12006-12-08 02:38:37 -08002988 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
2990 sreron = 0;
2991 sreroff = 0;
2992 if (tx == 0)
2993 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
2994 else if (tx == 1)
2995 sreron |= SRER_TXDATA;
2996 else if (tx >= 2)
2997 sreron |= SRER_TXEMPTY;
2998 if (rx == 0)
2999 sreroff |= SRER_RXDATA;
3000 else if (rx > 0)
3001 sreron |= SRER_RXDATA;
3002
Alan Coxb65b5b52006-06-27 02:54:05 -07003003 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 BRDENABLE(portp->brdnr, portp->pagenr);
3005 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3006 stl_cd1400setreg(portp, SRER,
3007 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3008 BRDDISABLE(portp->brdnr);
3009 if (tx > 0)
3010 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003011 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012}
3013
3014/*****************************************************************************/
3015
3016/*
3017 * Disable all interrupts from this port.
3018 */
3019
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003020static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021{
3022 unsigned long flags;
3023
Jiri Slabya0564e12006-12-08 02:38:37 -08003024 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3025
Alan Coxb65b5b52006-06-27 02:54:05 -07003026 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 BRDENABLE(portp->brdnr, portp->pagenr);
3028 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3029 stl_cd1400setreg(portp, SRER, 0);
3030 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003031 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032}
3033
3034/*****************************************************************************/
3035
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003036static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037{
3038 unsigned long flags;
3039
Jiri Slabya0564e12006-12-08 02:38:37 -08003040 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041
Alan Coxb65b5b52006-06-27 02:54:05 -07003042 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 BRDENABLE(portp->brdnr, portp->pagenr);
3044 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3045 stl_cd1400setreg(portp, SRER,
3046 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3047 SRER_TXEMPTY));
3048 BRDDISABLE(portp->brdnr);
3049 portp->brklen = len;
3050 if (len == 1)
3051 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003052 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053}
3054
3055/*****************************************************************************/
3056
3057/*
3058 * Take flow control actions...
3059 */
3060
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003061static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062{
3063 struct tty_struct *tty;
3064 unsigned long flags;
3065
Jiri Slabya0564e12006-12-08 02:38:37 -08003066 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Jiri Slaby615e4a72006-12-08 02:38:38 -08003068 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003070 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003071 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 return;
3073
Alan Coxb65b5b52006-06-27 02:54:05 -07003074 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 BRDENABLE(portp->brdnr, portp->pagenr);
3076 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3077
3078 if (state) {
3079 if (tty->termios->c_iflag & IXOFF) {
3080 stl_cd1400ccrwait(portp);
3081 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3082 portp->stats.rxxon++;
3083 stl_cd1400ccrwait(portp);
3084 }
3085/*
3086 * Question: should we return RTS to what it was before? It may
3087 * have been set by an ioctl... Suppose not, since if you have
3088 * hardware flow control set then it is pretty silly to go and
3089 * set the RTS line by hand.
3090 */
3091 if (tty->termios->c_cflag & CRTSCTS) {
3092 stl_cd1400setreg(portp, MCOR1,
3093 (stl_cd1400getreg(portp, MCOR1) |
3094 FIFO_RTSTHRESHOLD));
3095 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3096 portp->stats.rxrtson++;
3097 }
3098 } else {
3099 if (tty->termios->c_iflag & IXOFF) {
3100 stl_cd1400ccrwait(portp);
3101 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3102 portp->stats.rxxoff++;
3103 stl_cd1400ccrwait(portp);
3104 }
3105 if (tty->termios->c_cflag & CRTSCTS) {
3106 stl_cd1400setreg(portp, MCOR1,
3107 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3108 stl_cd1400setreg(portp, MSVR2, 0);
3109 portp->stats.rxrtsoff++;
3110 }
3111 }
3112
3113 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003114 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003115 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116}
3117
3118/*****************************************************************************/
3119
3120/*
3121 * Send a flow control character...
3122 */
3123
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003124static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125{
3126 struct tty_struct *tty;
3127 unsigned long flags;
3128
Jiri Slabya0564e12006-12-08 02:38:37 -08003129 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
Jiri Slaby615e4a72006-12-08 02:38:38 -08003131 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003133 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003134 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return;
3136
Alan Coxb65b5b52006-06-27 02:54:05 -07003137 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 BRDENABLE(portp->brdnr, portp->pagenr);
3139 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3140 if (state) {
3141 stl_cd1400ccrwait(portp);
3142 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3143 portp->stats.rxxon++;
3144 stl_cd1400ccrwait(portp);
3145 } else {
3146 stl_cd1400ccrwait(portp);
3147 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3148 portp->stats.rxxoff++;
3149 stl_cd1400ccrwait(portp);
3150 }
3151 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003152 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003153 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154}
3155
3156/*****************************************************************************/
3157
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003158static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159{
3160 unsigned long flags;
3161
Jiri Slabya0564e12006-12-08 02:38:37 -08003162 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163
Jiri Slaby615e4a72006-12-08 02:38:38 -08003164 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 return;
3166
Alan Coxb65b5b52006-06-27 02:54:05 -07003167 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 BRDENABLE(portp->brdnr, portp->pagenr);
3169 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3170 stl_cd1400ccrwait(portp);
3171 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3172 stl_cd1400ccrwait(portp);
3173 portp->tx.tail = portp->tx.head;
3174 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003175 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176}
3177
3178/*****************************************************************************/
3179
3180/*
3181 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02003182 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183 * transmission or not... This is easy for the cd1400, it accurately
3184 * maintains the busy port flag.
3185 */
3186
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003187static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188{
Jiri Slabya0564e12006-12-08 02:38:37 -08003189 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Jiri Slaby615e4a72006-12-08 02:38:38 -08003191 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003192 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Jesper Juhl014c2542006-01-15 02:37:08 +01003194 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196
3197/*****************************************************************************/
3198
3199/*
3200 * Interrupt service routine for cd1400 EasyIO boards.
3201 */
3202
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003203static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204{
3205 unsigned char svrtype;
3206
Jiri Slabya0564e12006-12-08 02:38:37 -08003207 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208
Alan Coxb65b5b52006-06-27 02:54:05 -07003209 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 outb(SVRR, iobase);
3211 svrtype = inb(iobase + EREG_DATA);
3212 if (panelp->nrports > 4) {
3213 outb((SVRR + 0x80), iobase);
3214 svrtype |= inb(iobase + EREG_DATA);
3215 }
3216
3217 if (svrtype & SVRR_RX)
3218 stl_cd1400rxisr(panelp, iobase);
3219 else if (svrtype & SVRR_TX)
3220 stl_cd1400txisr(panelp, iobase);
3221 else if (svrtype & SVRR_MDM)
3222 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003223
3224 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225}
3226
3227/*****************************************************************************/
3228
3229/*
3230 * Interrupt service routine for cd1400 panels.
3231 */
3232
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003233static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234{
3235 unsigned char svrtype;
3236
Jiri Slabya0564e12006-12-08 02:38:37 -08003237 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238
3239 outb(SVRR, iobase);
3240 svrtype = inb(iobase + EREG_DATA);
3241 outb((SVRR + 0x80), iobase);
3242 svrtype |= inb(iobase + EREG_DATA);
3243 if (svrtype & SVRR_RX)
3244 stl_cd1400rxisr(panelp, iobase);
3245 else if (svrtype & SVRR_TX)
3246 stl_cd1400txisr(panelp, iobase);
3247 else if (svrtype & SVRR_MDM)
3248 stl_cd1400mdmisr(panelp, iobase);
3249}
3250
3251
3252/*****************************************************************************/
3253
3254/*
3255 * Unfortunately we need to handle breaks in the TX data stream, since
3256 * this is the only way to generate them on the cd1400.
3257 */
3258
Jiri Slaby60be4812006-12-08 02:38:40 -08003259static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260{
3261 if (portp->brklen == 1) {
3262 outb((COR2 + portp->uartaddr), ioaddr);
3263 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3264 (ioaddr + EREG_DATA));
3265 outb((TDR + portp->uartaddr), ioaddr);
3266 outb(ETC_CMD, (ioaddr + EREG_DATA));
3267 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3268 outb((SRER + portp->uartaddr), ioaddr);
3269 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3270 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003271 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 } else if (portp->brklen > 1) {
3273 outb((TDR + portp->uartaddr), ioaddr);
3274 outb(ETC_CMD, (ioaddr + EREG_DATA));
3275 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3276 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003277 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 } else {
3279 outb((COR2 + portp->uartaddr), ioaddr);
3280 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3281 (ioaddr + EREG_DATA));
3282 portp->brklen = 0;
3283 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003284 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285}
3286
3287/*****************************************************************************/
3288
3289/*
3290 * Transmit interrupt handler. This has gotta be fast! Handling TX
3291 * chars is pretty simple, stuff as many as possible from the TX buffer
3292 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3293 * are embedded as commands in the data stream. Oh no, had to use a goto!
3294 * This could be optimized more, will do when I get time...
3295 * In practice it is possible that interrupts are enabled but that the
3296 * port has been hung up. Need to handle not having any TX buffer here,
3297 * this is done by using the side effect that head and tail will also
3298 * be NULL if the buffer has been freed.
3299 */
3300
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003301static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003303 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 int len, stlen;
3305 char *head, *tail;
3306 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003307 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308
Jiri Slabya0564e12006-12-08 02:38:37 -08003309 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
3311 ioack = inb(ioaddr + EREG_TXACK);
3312 if (((ioack & panelp->ackmask) != 0) ||
3313 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3314 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3315 return;
3316 }
3317 portp = panelp->ports[(ioack >> 3)];
3318
3319/*
3320 * Unfortunately we need to handle breaks in the data stream, since
3321 * this is the only way to generate them on the cd1400. Do it now if
3322 * a break is to be sent.
3323 */
3324 if (portp->brklen != 0)
3325 if (stl_cd1400breakisr(portp, ioaddr))
3326 goto stl_txalldone;
3327
3328 head = portp->tx.head;
3329 tail = portp->tx.tail;
3330 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3331 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3332 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3333 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003334 tty = tty_port_tty_get(&portp->port);
3335 if (tty) {
3336 tty_wakeup(tty);
3337 tty_kref_put(tty);
3338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 }
3340
3341 if (len == 0) {
3342 outb((SRER + portp->uartaddr), ioaddr);
3343 srer = inb(ioaddr + EREG_DATA);
3344 if (srer & SRER_TXDATA) {
3345 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3346 } else {
3347 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3348 clear_bit(ASYI_TXBUSY, &portp->istate);
3349 }
3350 outb(srer, (ioaddr + EREG_DATA));
3351 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003352 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003354 stlen = min_t(unsigned int, len,
3355 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 outb((TDR + portp->uartaddr), ioaddr);
3357 outsb((ioaddr + EREG_DATA), tail, stlen);
3358 len -= stlen;
3359 tail += stlen;
3360 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3361 tail = portp->tx.buf;
3362 if (len > 0) {
3363 outsb((ioaddr + EREG_DATA), tail, len);
3364 tail += len;
3365 }
3366 portp->tx.tail = tail;
3367 }
3368
3369stl_txalldone:
3370 outb((EOSRR + portp->uartaddr), ioaddr);
3371 outb(0, (ioaddr + EREG_DATA));
3372}
3373
3374/*****************************************************************************/
3375
3376/*
3377 * Receive character interrupt handler. Determine if we have good chars
3378 * or bad chars and then process appropriately. Good chars are easy
3379 * just shove the lot into the RX buffer and set all status byte to 0.
3380 * If a bad RX char then process as required. This routine needs to be
3381 * fast! In practice it is possible that we get an interrupt on a port
3382 * that is closed. This can happen on hangups - since they completely
3383 * shutdown a port not in user context. Need to handle this case.
3384 */
3385
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003386static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003388 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 struct tty_struct *tty;
3390 unsigned int ioack, len, buflen;
3391 unsigned char status;
3392 char ch;
3393
Jiri Slabya0564e12006-12-08 02:38:37 -08003394 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395
3396 ioack = inb(ioaddr + EREG_RXACK);
3397 if ((ioack & panelp->ackmask) != 0) {
3398 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3399 return;
3400 }
3401 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003402 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403
3404 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3405 outb((RDCR + portp->uartaddr), ioaddr);
3406 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003407 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003408 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 outb((RDSR + portp->uartaddr), ioaddr);
3410 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3411 portp->stats.rxlost += len;
3412 portp->stats.rxtotal += len;
3413 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003414 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003416 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003418 tty_prepare_flip_string(tty, &ptr, len);
3419 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 tty_schedule_flip(tty);
3421 portp->stats.rxtotal += len;
3422 }
3423 }
3424 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3425 outb((RDSR + portp->uartaddr), ioaddr);
3426 status = inb(ioaddr + EREG_DATA);
3427 ch = inb(ioaddr + EREG_DATA);
3428 if (status & ST_PARITY)
3429 portp->stats.rxparity++;
3430 if (status & ST_FRAMING)
3431 portp->stats.rxframing++;
3432 if (status & ST_OVERRUN)
3433 portp->stats.rxoverrun++;
3434 if (status & ST_BREAK)
3435 portp->stats.rxbreaks++;
3436 if (status & ST_SCHARMASK) {
3437 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3438 portp->stats.txxon++;
3439 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3440 portp->stats.txxoff++;
3441 goto stl_rxalldone;
3442 }
Alan Cox33f0f882006-01-09 20:54:13 -08003443 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 if (portp->rxmarkmsk & status) {
3445 if (status & ST_BREAK) {
3446 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003447 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448 do_SAK(tty);
3449 BRDENABLE(portp->brdnr, portp->pagenr);
3450 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003451 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003453 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003455 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003457 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003459 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003461 tty_insert_flip_char(tty, ch, status);
3462 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 }
3464 } else {
3465 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003466 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 return;
3468 }
3469
3470stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003471 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 outb((EOSRR + portp->uartaddr), ioaddr);
3473 outb(0, (ioaddr + EREG_DATA));
3474}
3475
3476/*****************************************************************************/
3477
3478/*
3479 * Modem interrupt handler. The is called when the modem signal line
3480 * (DCD) has changed state. Leave most of the work to the off-level
3481 * processing routine.
3482 */
3483
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003484static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003486 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 unsigned int ioack;
3488 unsigned char misr;
3489
Jiri Slabya0564e12006-12-08 02:38:37 -08003490 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
3492 ioack = inb(ioaddr + EREG_MDACK);
3493 if (((ioack & panelp->ackmask) != 0) ||
3494 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3495 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3496 return;
3497 }
3498 portp = panelp->ports[(ioack >> 3)];
3499
3500 outb((MISR + portp->uartaddr), ioaddr);
3501 misr = inb(ioaddr + EREG_DATA);
3502 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003503 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 portp->stats.modem++;
3505 }
3506
3507 outb((EOSRR + portp->uartaddr), ioaddr);
3508 outb(0, (ioaddr + EREG_DATA));
3509}
3510
3511/*****************************************************************************/
3512/* SC26198 HARDWARE FUNCTIONS */
3513/*****************************************************************************/
3514
3515/*
3516 * These functions get/set/update the registers of the sc26198 UARTs.
3517 * Access to the sc26198 registers is via an address/data io port pair.
3518 * (Maybe should make this inline...)
3519 */
3520
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003521static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522{
3523 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003524 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525}
3526
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003527static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528{
3529 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3530 outb(value, (portp->ioaddr + XP_DATA));
3531}
3532
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003533static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
3535 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3536 if (inb(portp->ioaddr + XP_DATA) != value) {
3537 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003538 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003540 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541}
3542
3543/*****************************************************************************/
3544
3545/*
3546 * Functions to get and set the sc26198 global registers.
3547 */
3548
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003549static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550{
3551 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003552 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553}
3554
3555#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003556static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
3558 outb(regnr, (portp->ioaddr + XP_ADDR));
3559 outb(value, (portp->ioaddr + XP_DATA));
3560}
3561#endif
3562
3563/*****************************************************************************/
3564
3565/*
3566 * Inbitialize the UARTs in a panel. We don't care what sort of board
3567 * these ports are on - since the port io registers are almost
3568 * identical when dealing with ports.
3569 */
3570
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003571static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572{
3573 int chipmask, i;
3574 int nrchips, ioaddr;
3575
Jiri Slabya0564e12006-12-08 02:38:37 -08003576 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577
3578 BRDENABLE(panelp->brdnr, panelp->pagenr);
3579
3580/*
3581 * Check that each chip is present and started up OK.
3582 */
3583 chipmask = 0;
3584 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3585 if (brdp->brdtype == BRD_ECHPCI)
3586 outb(panelp->pagenr, brdp->ioctrl);
3587
Jiri Slabyc62429d2006-12-08 02:39:14 -08003588 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 ioaddr = panelp->iobase + (i * 4);
3590 outb(SCCR, (ioaddr + XP_ADDR));
3591 outb(CR_RESETALL, (ioaddr + XP_DATA));
3592 outb(TSTR, (ioaddr + XP_ADDR));
3593 if (inb(ioaddr + XP_DATA) != 0) {
3594 printk("STALLION: sc26198 not responding, "
3595 "brd=%d panel=%d chip=%d\n",
3596 panelp->brdnr, panelp->panelnr, i);
3597 continue;
3598 }
3599 chipmask |= (0x1 << i);
3600 outb(GCCR, (ioaddr + XP_ADDR));
3601 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3602 outb(WDTRCR, (ioaddr + XP_ADDR));
3603 outb(0xff, (ioaddr + XP_DATA));
3604 }
3605
3606 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003607 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608}
3609
3610/*****************************************************************************/
3611
3612/*
3613 * Initialize hardware specific port registers.
3614 */
3615
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003616static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617{
Jiri Slabya0564e12006-12-08 02:38:37 -08003618 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3619 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620
Jiri Slaby615e4a72006-12-08 02:38:38 -08003621 if ((brdp == NULL) || (panelp == NULL) ||
3622 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 return;
3624
3625 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3626 portp->uartaddr = (portp->portnr & 0x07) << 4;
3627 portp->pagenr = panelp->pagenr;
3628 portp->hwid = 0x1;
3629
3630 BRDENABLE(portp->brdnr, portp->pagenr);
3631 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3632 BRDDISABLE(portp->brdnr);
3633}
3634
3635/*****************************************************************************/
3636
3637/*
3638 * Set up the sc26198 registers for a port based on the termios port
3639 * settings.
3640 */
3641
Alan Cox606d0992006-12-08 02:38:45 -08003642static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003644 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 unsigned long flags;
3646 unsigned int baudrate;
3647 unsigned char mr0, mr1, mr2, clk;
3648 unsigned char imron, imroff, iopr, ipr;
3649
3650 mr0 = 0;
3651 mr1 = 0;
3652 mr2 = 0;
3653 clk = 0;
3654 iopr = 0;
3655 imron = 0;
3656 imroff = 0;
3657
3658 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003659 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 return;
3661
3662/*
3663 * Set up the RX char ignore mask with those RX error types we
3664 * can ignore.
3665 */
3666 portp->rxignoremsk = 0;
3667 if (tiosp->c_iflag & IGNPAR)
3668 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3669 SR_RXOVERRUN);
3670 if (tiosp->c_iflag & IGNBRK)
3671 portp->rxignoremsk |= SR_RXBREAK;
3672
3673 portp->rxmarkmsk = SR_RXOVERRUN;
3674 if (tiosp->c_iflag & (INPCK | PARMRK))
3675 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3676 if (tiosp->c_iflag & BRKINT)
3677 portp->rxmarkmsk |= SR_RXBREAK;
3678
3679/*
3680 * Go through the char size, parity and stop bits and set all the
3681 * option register appropriately.
3682 */
3683 switch (tiosp->c_cflag & CSIZE) {
3684 case CS5:
3685 mr1 |= MR1_CS5;
3686 break;
3687 case CS6:
3688 mr1 |= MR1_CS6;
3689 break;
3690 case CS7:
3691 mr1 |= MR1_CS7;
3692 break;
3693 default:
3694 mr1 |= MR1_CS8;
3695 break;
3696 }
3697
3698 if (tiosp->c_cflag & CSTOPB)
3699 mr2 |= MR2_STOP2;
3700 else
3701 mr2 |= MR2_STOP1;
3702
3703 if (tiosp->c_cflag & PARENB) {
3704 if (tiosp->c_cflag & PARODD)
3705 mr1 |= (MR1_PARENB | MR1_PARODD);
3706 else
3707 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003708 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
3711 mr1 |= MR1_ERRBLOCK;
3712
3713/*
3714 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3715 * space for hardware flow control and the like. This should be set to
3716 * VMIN.
3717 */
3718 mr2 |= MR2_RXFIFOHALF;
3719
3720/*
3721 * Calculate the baud rate timers. For now we will just assume that
3722 * the input and output baud are the same. The sc26198 has a fixed
3723 * baud rate table, so only discrete baud rates possible.
3724 */
3725 baudrate = tiosp->c_cflag & CBAUD;
3726 if (baudrate & CBAUDEX) {
3727 baudrate &= ~CBAUDEX;
3728 if ((baudrate < 1) || (baudrate > 4))
3729 tiosp->c_cflag &= ~CBAUDEX;
3730 else
3731 baudrate += 15;
3732 }
3733 baudrate = stl_baudrates[baudrate];
3734 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003735 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003737 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003739 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003741 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003743 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744 baudrate = (portp->baud_base / portp->custom_divisor);
3745 }
3746 if (baudrate > STL_SC26198MAXBAUD)
3747 baudrate = STL_SC26198MAXBAUD;
3748
Jiri Slabyc62429d2006-12-08 02:39:14 -08003749 if (baudrate > 0)
3750 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 if (baudrate <= sc26198_baudtable[clk])
3752 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753
3754/*
3755 * Check what form of modem signaling is required and set it up.
3756 */
3757 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003758 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759 } else {
3760 iopr |= IOPR_DCDCOS;
3761 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003762 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 }
3764
3765/*
3766 * Setup sc26198 enhanced modes if we can. In particular we want to
3767 * handle as much of the flow control as possible automatically. As
3768 * well as saving a few CPU cycles it will also greatly improve flow
3769 * control reliability.
3770 */
3771 if (tiosp->c_iflag & IXON) {
3772 mr0 |= MR0_SWFTX | MR0_SWFT;
3773 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003774 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003776
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 if (tiosp->c_iflag & IXOFF)
3778 mr0 |= MR0_SWFRX;
3779
3780 if (tiosp->c_cflag & CRTSCTS) {
3781 mr2 |= MR2_AUTOCTS;
3782 mr1 |= MR1_AUTORTS;
3783 }
3784
3785/*
3786 * All sc26198 register values calculated so go through and set
3787 * them all up.
3788 */
3789
Jiri Slabya0564e12006-12-08 02:38:37 -08003790 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003792 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3793 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3794 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3796 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797
Alan Coxb65b5b52006-06-27 02:54:05 -07003798 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 BRDENABLE(portp->brdnr, portp->pagenr);
3800 stl_sc26198setreg(portp, IMR, 0);
3801 stl_sc26198updatereg(portp, MR0, mr0);
3802 stl_sc26198updatereg(portp, MR1, mr1);
3803 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3804 stl_sc26198updatereg(portp, MR2, mr2);
3805 stl_sc26198updatereg(portp, IOPIOR,
3806 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3807
3808 if (baudrate > 0) {
3809 stl_sc26198setreg(portp, TXCSR, clk);
3810 stl_sc26198setreg(portp, RXCSR, clk);
3811 }
3812
3813 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3814 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3815
3816 ipr = stl_sc26198getreg(portp, IPR);
3817 if (ipr & IPR_DCD)
3818 portp->sigs &= ~TIOCM_CD;
3819 else
3820 portp->sigs |= TIOCM_CD;
3821
3822 portp->imr = (portp->imr & ~imroff) | imron;
3823 stl_sc26198setreg(portp, IMR, portp->imr);
3824 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003825 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826}
3827
3828/*****************************************************************************/
3829
3830/*
3831 * Set the state of the DTR and RTS signals.
3832 */
3833
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003834static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835{
3836 unsigned char iopioron, iopioroff;
3837 unsigned long flags;
3838
Jiri Slabya0564e12006-12-08 02:38:37 -08003839 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3840 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
3842 iopioron = 0;
3843 iopioroff = 0;
3844 if (dtr == 0)
3845 iopioroff |= IPR_DTR;
3846 else if (dtr > 0)
3847 iopioron |= IPR_DTR;
3848 if (rts == 0)
3849 iopioroff |= IPR_RTS;
3850 else if (rts > 0)
3851 iopioron |= IPR_RTS;
3852
Alan Coxb65b5b52006-06-27 02:54:05 -07003853 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854 BRDENABLE(portp->brdnr, portp->pagenr);
3855 stl_sc26198setreg(portp, IOPIOR,
3856 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3857 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003858 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859}
3860
3861/*****************************************************************************/
3862
3863/*
3864 * Return the state of the signals.
3865 */
3866
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003867static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868{
3869 unsigned char ipr;
3870 unsigned long flags;
3871 int sigs;
3872
Jiri Slabya0564e12006-12-08 02:38:37 -08003873 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Alan Coxb65b5b52006-06-27 02:54:05 -07003875 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 BRDENABLE(portp->brdnr, portp->pagenr);
3877 ipr = stl_sc26198getreg(portp, IPR);
3878 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003879 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
3881 sigs = 0;
3882 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3883 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3884 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3885 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3886 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003887 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
3890/*****************************************************************************/
3891
3892/*
3893 * Enable/Disable the Transmitter and/or Receiver.
3894 */
3895
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003896static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897{
3898 unsigned char ccr;
3899 unsigned long flags;
3900
Jiri Slabya0564e12006-12-08 02:38:37 -08003901 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902
3903 ccr = portp->crenable;
3904 if (tx == 0)
3905 ccr &= ~CR_TXENABLE;
3906 else if (tx > 0)
3907 ccr |= CR_TXENABLE;
3908 if (rx == 0)
3909 ccr &= ~CR_RXENABLE;
3910 else if (rx > 0)
3911 ccr |= CR_RXENABLE;
3912
Alan Coxb65b5b52006-06-27 02:54:05 -07003913 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 BRDENABLE(portp->brdnr, portp->pagenr);
3915 stl_sc26198setreg(portp, SCCR, ccr);
3916 BRDDISABLE(portp->brdnr);
3917 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003918 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919}
3920
3921/*****************************************************************************/
3922
3923/*
3924 * Start/stop the Transmitter and/or Receiver.
3925 */
3926
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003927static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928{
3929 unsigned char imr;
3930 unsigned long flags;
3931
Jiri Slabya0564e12006-12-08 02:38:37 -08003932 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
3934 imr = portp->imr;
3935 if (tx == 0)
3936 imr &= ~IR_TXRDY;
3937 else if (tx == 1)
3938 imr |= IR_TXRDY;
3939 if (rx == 0)
3940 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3941 else if (rx > 0)
3942 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3943
Alan Coxb65b5b52006-06-27 02:54:05 -07003944 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 BRDENABLE(portp->brdnr, portp->pagenr);
3946 stl_sc26198setreg(portp, IMR, imr);
3947 BRDDISABLE(portp->brdnr);
3948 portp->imr = imr;
3949 if (tx > 0)
3950 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003951 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952}
3953
3954/*****************************************************************************/
3955
3956/*
3957 * Disable all interrupts from this port.
3958 */
3959
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003960static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961{
3962 unsigned long flags;
3963
Jiri Slabya0564e12006-12-08 02:38:37 -08003964 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
Alan Coxb65b5b52006-06-27 02:54:05 -07003966 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 BRDENABLE(portp->brdnr, portp->pagenr);
3968 portp->imr = 0;
3969 stl_sc26198setreg(portp, IMR, 0);
3970 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003971 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972}
3973
3974/*****************************************************************************/
3975
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003976static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977{
3978 unsigned long flags;
3979
Jiri Slabya0564e12006-12-08 02:38:37 -08003980 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Alan Coxb65b5b52006-06-27 02:54:05 -07003982 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983 BRDENABLE(portp->brdnr, portp->pagenr);
3984 if (len == 1) {
3985 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
3986 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003987 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003989
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003991 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992}
3993
3994/*****************************************************************************/
3995
3996/*
3997 * Take flow control actions...
3998 */
3999
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004000static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001{
4002 struct tty_struct *tty;
4003 unsigned long flags;
4004 unsigned char mr0;
4005
Jiri Slabya0564e12006-12-08 02:38:37 -08004006 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Jiri Slaby615e4a72006-12-08 02:38:38 -08004008 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004010 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004011 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 return;
4013
Alan Coxb65b5b52006-06-27 02:54:05 -07004014 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 BRDENABLE(portp->brdnr, portp->pagenr);
4016
4017 if (state) {
4018 if (tty->termios->c_iflag & IXOFF) {
4019 mr0 = stl_sc26198getreg(portp, MR0);
4020 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4021 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4022 mr0 |= MR0_SWFRX;
4023 portp->stats.rxxon++;
4024 stl_sc26198wait(portp);
4025 stl_sc26198setreg(portp, MR0, mr0);
4026 }
4027/*
4028 * Question: should we return RTS to what it was before? It may
4029 * have been set by an ioctl... Suppose not, since if you have
4030 * hardware flow control set then it is pretty silly to go and
4031 * set the RTS line by hand.
4032 */
4033 if (tty->termios->c_cflag & CRTSCTS) {
4034 stl_sc26198setreg(portp, MR1,
4035 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4036 stl_sc26198setreg(portp, IOPIOR,
4037 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4038 portp->stats.rxrtson++;
4039 }
4040 } else {
4041 if (tty->termios->c_iflag & IXOFF) {
4042 mr0 = stl_sc26198getreg(portp, MR0);
4043 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4044 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4045 mr0 &= ~MR0_SWFRX;
4046 portp->stats.rxxoff++;
4047 stl_sc26198wait(portp);
4048 stl_sc26198setreg(portp, MR0, mr0);
4049 }
4050 if (tty->termios->c_cflag & CRTSCTS) {
4051 stl_sc26198setreg(portp, MR1,
4052 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4053 stl_sc26198setreg(portp, IOPIOR,
4054 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4055 portp->stats.rxrtsoff++;
4056 }
4057 }
4058
4059 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004060 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004061 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062}
4063
4064/*****************************************************************************/
4065
4066/*
4067 * Send a flow control character.
4068 */
4069
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004070static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071{
4072 struct tty_struct *tty;
4073 unsigned long flags;
4074 unsigned char mr0;
4075
Jiri Slabya0564e12006-12-08 02:38:37 -08004076 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Jiri Slaby615e4a72006-12-08 02:38:38 -08004078 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004080 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004081 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 return;
4083
Alan Coxb65b5b52006-06-27 02:54:05 -07004084 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 BRDENABLE(portp->brdnr, portp->pagenr);
4086 if (state) {
4087 mr0 = stl_sc26198getreg(portp, MR0);
4088 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4089 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4090 mr0 |= MR0_SWFRX;
4091 portp->stats.rxxon++;
4092 stl_sc26198wait(portp);
4093 stl_sc26198setreg(portp, MR0, mr0);
4094 } else {
4095 mr0 = stl_sc26198getreg(portp, MR0);
4096 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4097 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4098 mr0 &= ~MR0_SWFRX;
4099 portp->stats.rxxoff++;
4100 stl_sc26198wait(portp);
4101 stl_sc26198setreg(portp, MR0, mr0);
4102 }
4103 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004104 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004105 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106}
4107
4108/*****************************************************************************/
4109
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004110static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111{
4112 unsigned long flags;
4113
Jiri Slabya0564e12006-12-08 02:38:37 -08004114 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Jiri Slaby615e4a72006-12-08 02:38:38 -08004116 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 return;
4118
Alan Coxb65b5b52006-06-27 02:54:05 -07004119 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 BRDENABLE(portp->brdnr, portp->pagenr);
4121 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4122 stl_sc26198setreg(portp, SCCR, portp->crenable);
4123 BRDDISABLE(portp->brdnr);
4124 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004125 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126}
4127
4128/*****************************************************************************/
4129
4130/*
4131 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02004132 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 * transmission or not... The sc26198 interrupt scheme cannot
4134 * determine when all data has actually drained, so we need to
4135 * check the port statusy register to be sure.
4136 */
4137
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004138static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139{
4140 unsigned long flags;
4141 unsigned char sr;
4142
Jiri Slabya0564e12006-12-08 02:38:37 -08004143 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
Jiri Slaby615e4a72006-12-08 02:38:38 -08004145 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004146 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004148 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
Alan Coxb65b5b52006-06-27 02:54:05 -07004150 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 BRDENABLE(portp->brdnr, portp->pagenr);
4152 sr = stl_sc26198getreg(portp, SR);
4153 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004154 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Jesper Juhl014c2542006-01-15 02:37:08 +01004156 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157}
4158
4159/*****************************************************************************/
4160
4161/*
4162 * Delay for a small amount of time, to give the sc26198 a chance
4163 * to process a command...
4164 */
4165
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004166static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167{
4168 int i;
4169
Jiri Slabya0564e12006-12-08 02:38:37 -08004170 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
Jiri Slaby615e4a72006-12-08 02:38:38 -08004172 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 return;
4174
Jiri Slabyc62429d2006-12-08 02:39:14 -08004175 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 stl_sc26198getglobreg(portp, TSTR);
4177}
4178
4179/*****************************************************************************/
4180
4181/*
4182 * If we are TX flow controlled and in IXANY mode then we may
4183 * need to unflow control here. We gotta do this because of the
4184 * automatic flow control modes of the sc26198.
4185 */
4186
Jiri Slaby60be4812006-12-08 02:38:40 -08004187static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188{
4189 unsigned char mr0;
4190
4191 mr0 = stl_sc26198getreg(portp, MR0);
4192 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4193 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4194 stl_sc26198wait(portp);
4195 stl_sc26198setreg(portp, MR0, mr0);
4196 clear_bit(ASYI_TXFLOWED, &portp->istate);
4197}
4198
4199/*****************************************************************************/
4200
4201/*
4202 * Interrupt service routine for sc26198 panels.
4203 */
4204
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004205static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004207 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 unsigned int iack;
4209
Alan Coxb65b5b52006-06-27 02:54:05 -07004210 spin_lock(&brd_lock);
4211
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212/*
4213 * Work around bug in sc26198 chip... Cannot have A6 address
4214 * line of UART high, else iack will be returned as 0.
4215 */
4216 outb(0, (iobase + 1));
4217
4218 iack = inb(iobase + XP_IACK);
4219 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4220
4221 if (iack & IVR_RXDATA)
4222 stl_sc26198rxisr(portp, iack);
4223 else if (iack & IVR_TXDATA)
4224 stl_sc26198txisr(portp);
4225 else
4226 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004227
4228 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229}
4230
4231/*****************************************************************************/
4232
4233/*
4234 * Transmit interrupt handler. This has gotta be fast! Handling TX
4235 * chars is pretty simple, stuff as many as possible from the TX buffer
4236 * into the sc26198 FIFO.
4237 * In practice it is possible that interrupts are enabled but that the
4238 * port has been hung up. Need to handle not having any TX buffer here,
4239 * this is done by using the side effect that head and tail will also
4240 * be NULL if the buffer has been freed.
4241 */
4242
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004243static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244{
Alan Coxd18a7502008-10-13 10:40:07 +01004245 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 unsigned int ioaddr;
4247 unsigned char mr0;
4248 int len, stlen;
4249 char *head, *tail;
4250
Jiri Slabya0564e12006-12-08 02:38:37 -08004251 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
4253 ioaddr = portp->ioaddr;
4254 head = portp->tx.head;
4255 tail = portp->tx.tail;
4256 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4257 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4258 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4259 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004260 tty = tty_port_tty_get(&portp->port);
4261 if (tty) {
4262 tty_wakeup(tty);
4263 tty_kref_put(tty);
4264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 }
4266
4267 if (len == 0) {
4268 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4269 mr0 = inb(ioaddr + XP_DATA);
4270 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4271 portp->imr &= ~IR_TXRDY;
4272 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4273 outb(portp->imr, (ioaddr + XP_DATA));
4274 clear_bit(ASYI_TXBUSY, &portp->istate);
4275 } else {
4276 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4277 outb(mr0, (ioaddr + XP_DATA));
4278 }
4279 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004280 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004282 stlen = min_t(unsigned int, len,
4283 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 outb(GTXFIFO, (ioaddr + XP_ADDR));
4285 outsb((ioaddr + XP_DATA), tail, stlen);
4286 len -= stlen;
4287 tail += stlen;
4288 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4289 tail = portp->tx.buf;
4290 if (len > 0) {
4291 outsb((ioaddr + XP_DATA), tail, len);
4292 tail += len;
4293 }
4294 portp->tx.tail = tail;
4295 }
4296}
4297
4298/*****************************************************************************/
4299
4300/*
4301 * Receive character interrupt handler. Determine if we have good chars
4302 * or bad chars and then process appropriately. Good chars are easy
4303 * just shove the lot into the RX buffer and set all status byte to 0.
4304 * If a bad RX char then process as required. This routine needs to be
4305 * fast! In practice it is possible that we get an interrupt on a port
4306 * that is closed. This can happen on hangups - since they completely
4307 * shutdown a port not in user context. Need to handle this case.
4308 */
4309
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004310static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311{
4312 struct tty_struct *tty;
4313 unsigned int len, buflen, ioaddr;
4314
Jiri Slabya0564e12006-12-08 02:38:37 -08004315 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316
Alan Coxd18a7502008-10-13 10:40:07 +01004317 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 ioaddr = portp->ioaddr;
4319 outb(GIBCR, (ioaddr + XP_ADDR));
4320 len = inb(ioaddr + XP_DATA) + 1;
4321
4322 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004323 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004324 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 outb(GRXFIFO, (ioaddr + XP_ADDR));
4326 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4327 portp->stats.rxlost += len;
4328 portp->stats.rxtotal += len;
4329 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004330 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004332 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004334 tty_prepare_flip_string(tty, &ptr, len);
4335 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 tty_schedule_flip(tty);
4337 portp->stats.rxtotal += len;
4338 }
4339 }
4340 } else {
4341 stl_sc26198rxbadchars(portp);
4342 }
4343
4344/*
4345 * If we are TX flow controlled and in IXANY mode then we may need
4346 * to unflow control here. We gotta do this because of the automatic
4347 * flow control modes of the sc26198.
4348 */
4349 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004350 if ((tty != NULL) &&
4351 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 (tty->termios->c_iflag & IXANY)) {
4353 stl_sc26198txunflow(portp, tty);
4354 }
4355 }
Alan Coxd18a7502008-10-13 10:40:07 +01004356 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357}
4358
4359/*****************************************************************************/
4360
4361/*
4362 * Process an RX bad character.
4363 */
4364
Jiri Slaby60be4812006-12-08 02:38:40 -08004365static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366{
4367 struct tty_struct *tty;
4368 unsigned int ioaddr;
4369
Alan Coxd18a7502008-10-13 10:40:07 +01004370 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 ioaddr = portp->ioaddr;
4372
4373 if (status & SR_RXPARITY)
4374 portp->stats.rxparity++;
4375 if (status & SR_RXFRAMING)
4376 portp->stats.rxframing++;
4377 if (status & SR_RXOVERRUN)
4378 portp->stats.rxoverrun++;
4379 if (status & SR_RXBREAK)
4380 portp->stats.rxbreaks++;
4381
Jiri Slaby615e4a72006-12-08 02:38:38 -08004382 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383 ((portp->rxignoremsk & status) == 0)) {
4384 if (portp->rxmarkmsk & status) {
4385 if (status & SR_RXBREAK) {
4386 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004387 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388 do_SAK(tty);
4389 BRDENABLE(portp->brdnr, portp->pagenr);
4390 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004391 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004393 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004395 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004397 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004399 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Alan Cox33f0f882006-01-09 20:54:13 -08004402 tty_insert_flip_char(tty, ch, status);
4403 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404
4405 if (status == 0)
4406 portp->stats.rxtotal++;
4407 }
Alan Coxd18a7502008-10-13 10:40:07 +01004408 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409}
4410
4411/*****************************************************************************/
4412
4413/*
4414 * Process all characters in the RX FIFO of the UART. Check all char
4415 * status bytes as well, and process as required. We need to check
4416 * all bytes in the FIFO, in case some more enter the FIFO while we
4417 * are here. To get the exact character error type we need to switch
4418 * into CHAR error mode (that is why we need to make sure we empty
4419 * the FIFO).
4420 */
4421
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004422static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423{
4424 unsigned char status, mr1;
4425 char ch;
4426
4427/*
4428 * To get the precise error type for each character we must switch
4429 * back into CHAR error mode.
4430 */
4431 mr1 = stl_sc26198getreg(portp, MR1);
4432 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4433
4434 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4435 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4436 ch = stl_sc26198getreg(portp, RXFIFO);
4437 stl_sc26198rxbadch(portp, status, ch);
4438 }
4439
4440/*
4441 * To get correct interrupt class we must switch back into BLOCK
4442 * error mode.
4443 */
4444 stl_sc26198setreg(portp, MR1, mr1);
4445}
4446
4447/*****************************************************************************/
4448
4449/*
4450 * Other interrupt handler. This includes modem signals, flow
4451 * control actions, etc. Most stuff is left to off-level interrupt
4452 * processing time.
4453 */
4454
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004455static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456{
4457 unsigned char cir, ipr, xisr;
4458
Jiri Slabya0564e12006-12-08 02:38:37 -08004459 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460
4461 cir = stl_sc26198getglobreg(portp, CIR);
4462
4463 switch (cir & CIR_SUBTYPEMASK) {
4464 case CIR_SUBCOS:
4465 ipr = stl_sc26198getreg(portp, IPR);
4466 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004467 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 portp->stats.modem++;
4469 }
4470 break;
4471 case CIR_SUBXONXOFF:
4472 xisr = stl_sc26198getreg(portp, XISR);
4473 if (xisr & XISR_RXXONGOT) {
4474 set_bit(ASYI_TXFLOWED, &portp->istate);
4475 portp->stats.txxoff++;
4476 }
4477 if (xisr & XISR_RXXOFFGOT) {
4478 clear_bit(ASYI_TXFLOWED, &portp->istate);
4479 portp->stats.txxon++;
4480 }
4481 break;
4482 case CIR_SUBBREAK:
4483 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4484 stl_sc26198rxbadchars(portp);
4485 break;
4486 default:
4487 break;
4488 }
4489}
4490
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004491static void stl_free_isabrds(void)
4492{
4493 struct stlbrd *brdp;
4494 unsigned int i;
4495
4496 for (i = 0; i < stl_nrbrds; i++) {
4497 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4498 continue;
4499
4500 free_irq(brdp->irq, brdp);
4501
4502 stl_cleanup_panels(brdp);
4503
4504 release_region(brdp->ioaddr1, brdp->iosize1);
4505 if (brdp->iosize2 > 0)
4506 release_region(brdp->ioaddr2, brdp->iosize2);
4507
4508 kfree(brdp);
4509 stl_brds[i] = NULL;
4510 }
4511}
4512
Jiri Slaby23b85a12006-12-08 02:38:40 -08004513/*
4514 * Loadable module initialization stuff.
4515 */
4516static int __init stallion_module_init(void)
4517{
Jiri Slaby843b5682006-12-08 02:39:12 -08004518 struct stlbrd *brdp;
4519 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004520 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004521 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004522
4523 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4524
4525 spin_lock_init(&stallion_lock);
4526 spin_lock_init(&brd_lock);
4527
Jiri Slabye4151092007-06-08 13:46:52 -07004528 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4529 if (!stl_serial) {
4530 retval = -ENOMEM;
4531 goto err;
4532 }
4533
4534 stl_serial->owner = THIS_MODULE;
4535 stl_serial->driver_name = stl_drvname;
4536 stl_serial->name = "ttyE";
4537 stl_serial->major = STL_SERIALMAJOR;
4538 stl_serial->minor_start = 0;
4539 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4540 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4541 stl_serial->init_termios = stl_deftermios;
4542 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4543 tty_set_operations(stl_serial, &stl_ops);
4544
4545 retval = tty_register_driver(stl_serial);
4546 if (retval) {
4547 printk("STALLION: failed to register serial driver\n");
4548 goto err_frtty;
4549 }
4550
Jiri Slaby843b5682006-12-08 02:39:12 -08004551/*
4552 * Find any dynamically supported boards. That is via module load
4553 * line options.
4554 */
4555 for (i = stl_nrbrds; i < stl_nargs; i++) {
4556 memset(&conf, 0, sizeof(conf));
4557 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4558 continue;
4559 if ((brdp = stl_allocbrd()) == NULL)
4560 continue;
4561 brdp->brdnr = i;
4562 brdp->brdtype = conf.brdtype;
4563 brdp->ioaddr1 = conf.ioaddr1;
4564 brdp->ioaddr2 = conf.ioaddr2;
4565 brdp->irq = conf.irq;
4566 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004567 stl_brds[brdp->brdnr] = brdp;
4568 if (stl_brdinit(brdp)) {
4569 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004570 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004571 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004572 for (j = 0; j < brdp->nrports; j++)
4573 tty_register_device(stl_serial,
4574 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004575 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004576 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004577 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004578
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004579 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004580 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004581 if (retval && stl_nrbrds == 0) {
4582 printk(KERN_ERR "STALLION: can't register pci driver\n");
4583 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004584 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004585
4586/*
4587 * Set up a character driver for per board stuff. This is mainly used
4588 * to do stats ioctls on the ports.
4589 */
4590 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4591 printk("STALLION: failed to register serial board device\n");
4592
4593 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004594 if (IS_ERR(stallion_class))
4595 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004596 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004597 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4598 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004599
Jiri Slaby23b85a12006-12-08 02:38:40 -08004600 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004601err_unrtty:
4602 tty_unregister_driver(stl_serial);
4603err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004604 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004605err:
4606 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004607}
4608
4609static void __exit stallion_module_exit(void)
4610{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004611 struct stlbrd *brdp;
4612 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004613
4614 pr_debug("cleanup_module()\n");
4615
4616 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4617 stl_drvversion);
4618
4619/*
4620 * Free up all allocated resources used by the ports. This includes
4621 * memory and interrupts. As part of this process we will also do
4622 * a hangup on every open port - to try to flush out any processes
4623 * hanging onto ports.
4624 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004625 for (i = 0; i < stl_nrbrds; i++) {
4626 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4627 continue;
4628 for (j = 0; j < brdp->nrports; j++)
4629 tty_unregister_device(stl_serial,
4630 brdp->brdnr * STL_MAXPORTS + j);
4631 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004632
Jiri Slaby23b85a12006-12-08 02:38:40 -08004633 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004634 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004635 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004636 class_destroy(stallion_class);
4637
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004638 pci_unregister_driver(&stl_pcidriver);
4639
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004640 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004641
4642 tty_unregister_driver(stl_serial);
4643 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004644}
4645
4646module_init(stallion_module_init);
4647module_exit(stallion_module_exit);
4648
4649MODULE_AUTHOR("Greg Ungerer");
4650MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4651MODULE_LICENSE("GPL");