blob: 461a5a0455170b63807b1945451d69c9f1abd1fd [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
1097static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1098{
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
1110static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1111 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
1135static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1136{
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
Jiri Slabya0564e12006-12-08 02:38:37 -08001141 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1142 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001145 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001146 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
1148 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001149 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001151 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
1153 rc = 0;
1154
1155 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 case TIOCGSERIAL:
1157 rc = stl_getserial(portp, argp);
1158 break;
1159 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001160 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 break;
1162 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001163 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 break;
1165 case COM_CLRPORTSTATS:
1166 rc = stl_clrportstats(portp, argp);
1167 break;
1168 case TIOCSERCONFIG:
1169 case TIOCSERGWILD:
1170 case TIOCSERSWILD:
1171 case TIOCSERGETLSR:
1172 case TIOCSERGSTRUCT:
1173 case TIOCSERGETMULTI:
1174 case TIOCSERSETMULTI:
1175 default:
1176 rc = -ENOIOCTLCMD;
1177 break;
1178 }
Jesper Juhl014c2542006-01-15 02:37:08 +01001179 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180}
1181
1182/*****************************************************************************/
1183
Jiri Slaby96b066b2006-12-08 02:38:42 -08001184/*
1185 * Start the transmitter again. Just turn TX interrupts back on.
1186 */
1187
1188static void stl_start(struct tty_struct *tty)
1189{
1190 struct stlport *portp;
1191
1192 pr_debug("stl_start(tty=%p)\n", tty);
1193
Jiri Slaby96b066b2006-12-08 02:38:42 -08001194 portp = tty->driver_data;
1195 if (portp == NULL)
1196 return;
1197 stl_startrxtx(portp, -1, 1);
1198}
1199
1200/*****************************************************************************/
1201
Alan Cox606d0992006-12-08 02:38:45 -08001202static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001204 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001205 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Jiri Slabya0564e12006-12-08 02:38:37 -08001207 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001210 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 return;
1212
1213 tiosp = tty->termios;
1214 if ((tiosp->c_cflag == old->c_cflag) &&
1215 (tiosp->c_iflag == old->c_iflag))
1216 return;
1217
1218 stl_setport(portp, tiosp);
1219 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1220 -1);
1221 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1222 tty->hw_stopped = 0;
1223 stl_start(tty);
1224 }
1225 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001226 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227}
1228
1229/*****************************************************************************/
1230
1231/*
1232 * Attempt to flow control who ever is sending us data. Based on termios
1233 * settings use software or/and hardware flow control.
1234 */
1235
1236static void stl_throttle(struct tty_struct *tty)
1237{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001238 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Jiri Slabya0564e12006-12-08 02:38:37 -08001240 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001243 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 return;
1245 stl_flowctrl(portp, 0);
1246}
1247
1248/*****************************************************************************/
1249
1250/*
1251 * Unflow control the device sending us data...
1252 */
1253
1254static void stl_unthrottle(struct tty_struct *tty)
1255{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001256 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
Jiri Slabya0564e12006-12-08 02:38:37 -08001258 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001261 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 return;
1263 stl_flowctrl(portp, 1);
1264}
1265
1266/*****************************************************************************/
1267
1268/*
1269 * Stop the transmitter. Basically to do this we will just turn TX
1270 * interrupts off.
1271 */
1272
1273static void stl_stop(struct tty_struct *tty)
1274{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001275 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Jiri Slabya0564e12006-12-08 02:38:37 -08001277 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001280 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 return;
1282 stl_startrxtx(portp, -1, 0);
1283}
1284
1285/*****************************************************************************/
1286
1287/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 * Hangup this port. This is pretty much like closing the port, only
1289 * a little more brutal. No waiting for data to drain. Shutdown the
1290 * port and maybe drop signals.
1291 */
1292
1293static void stl_hangup(struct tty_struct *tty)
1294{
Alan Cox047e9652009-11-30 13:17:03 +00001295 struct stlport *portp = tty->driver_data;
Jiri Slabya0564e12006-12-08 02:38:37 -08001296 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Jiri Slaby615e4a72006-12-08 02:38:38 -08001298 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 return;
Alan Cox047e9652009-11-30 13:17:03 +00001300 tty_port_hangup(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301}
1302
1303/*****************************************************************************/
1304
David Howells4a561222008-07-22 11:18:43 +01001305static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001307 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Jiri Slabya0564e12006-12-08 02:38:37 -08001309 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001312 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001313 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
1315 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001316 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317}
1318
1319/*****************************************************************************/
1320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321static void stl_sendxchar(struct tty_struct *tty, char ch)
1322{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001323 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Jiri Slabya0564e12006-12-08 02:38:37 -08001325 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001328 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 return;
1330
1331 if (ch == STOP_CHAR(tty))
1332 stl_sendflow(portp, 0);
1333 else if (ch == START_CHAR(tty))
1334 stl_sendflow(portp, 1);
1335 else
1336 stl_putchar(tty, ch);
1337}
1338
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001339static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001341 int sigs;
1342 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001344 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1346 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1347
1348 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001349 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001351 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001353 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001355 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
1357 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001358 sep = ' ';
1359 if (sigs & TIOCM_RTS) {
1360 seq_printf(m, "%c%s", sep, "RTS");
1361 sep = '|';
1362 }
1363 if (sigs & TIOCM_CTS) {
1364 seq_printf(m, "%c%s", sep, "CTS");
1365 sep = '|';
1366 }
1367 if (sigs & TIOCM_DTR) {
1368 seq_printf(m, "%c%s", sep, "DTR");
1369 sep = '|';
1370 }
1371 if (sigs & TIOCM_CD) {
1372 seq_printf(m, "%c%s", sep, "DCD");
1373 sep = '|';
1374 }
1375 if (sigs & TIOCM_DSR) {
1376 seq_printf(m, "%c%s", sep, "DSR");
1377 sep = '|';
1378 }
1379 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380}
1381
1382/*****************************************************************************/
1383
1384/*
1385 * Port info, read from the /proc file system.
1386 */
1387
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001388static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001390 struct stlbrd *brdp;
1391 struct stlpanel *panelp;
1392 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001393 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001394 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001398 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
1400/*
1401 * We scan through for each board, panel and port. The offset is
1402 * calculated on the fly, and irrelevant ports are skipped.
1403 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001404 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001406 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 continue;
1408 if (brdp->state == 0)
1409 continue;
1410
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001412 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 continue;
1416
Jiri Slabyc62429d2006-12-08 02:39:14 -08001417 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 totalport++) {
1419 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001420 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001422 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 }
1424 }
1425 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001426 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427}
1428
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001429static int stl_proc_open(struct inode *inode, struct file *file)
1430{
1431 return single_open(file, stl_proc_show, NULL);
1432}
1433
1434static const struct file_operations stl_proc_fops = {
1435 .owner = THIS_MODULE,
1436 .open = stl_proc_open,
1437 .read = seq_read,
1438 .llseek = seq_lseek,
1439 .release = single_release,
1440};
1441
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442/*****************************************************************************/
1443
1444/*
1445 * All board interrupts are vectored through here first. This code then
1446 * calls off to the approrpriate board interrupt handlers.
1447 */
1448
David Howells7d12e782006-10-05 14:55:46 +01001449static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001451 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Jeff Garzika6f97b22007-10-31 05:20:49 -04001453 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 return IRQ_RETVAL((* brdp->isr)(brdp));
1456}
1457
1458/*****************************************************************************/
1459
1460/*
1461 * Interrupt service routine for EasyIO board types.
1462 */
1463
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001464static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001466 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 unsigned int iobase;
1468 int handled = 0;
1469
Alan Coxb65b5b52006-06-27 02:54:05 -07001470 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 panelp = brdp->panels[0];
1472 iobase = panelp->iobase;
1473 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1474 handled = 1;
1475 (* panelp->isr)(panelp, iobase);
1476 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001477 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 return handled;
1479}
1480
1481/*****************************************************************************/
1482
1483/*
1484 * Interrupt service routine for ECH-AT board types.
1485 */
1486
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001487static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001489 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001490 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 int handled = 0;
1492
1493 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1494
1495 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1496 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001497 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 ioaddr = brdp->bnkstataddr[bnknr];
1499 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1500 panelp = brdp->bnk2panel[bnknr];
1501 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1502 }
1503 }
1504 }
1505
1506 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1507
1508 return handled;
1509}
1510
1511/*****************************************************************************/
1512
1513/*
1514 * Interrupt service routine for ECH-MCA board types.
1515 */
1516
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001517static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001519 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001520 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 int handled = 0;
1522
1523 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1524 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001525 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 ioaddr = brdp->bnkstataddr[bnknr];
1527 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1528 panelp = brdp->bnk2panel[bnknr];
1529 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1530 }
1531 }
1532 }
1533 return handled;
1534}
1535
1536/*****************************************************************************/
1537
1538/*
1539 * Interrupt service routine for ECH-PCI board types.
1540 */
1541
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001542static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001544 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001545 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 int handled = 0;
1547
1548 while (1) {
1549 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001550 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1552 ioaddr = brdp->bnkstataddr[bnknr];
1553 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1554 panelp = brdp->bnk2panel[bnknr];
1555 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1556 recheck++;
1557 handled = 1;
1558 }
1559 }
1560 if (! recheck)
1561 break;
1562 }
1563 return handled;
1564}
1565
1566/*****************************************************************************/
1567
1568/*
1569 * Interrupt service routine for ECH-8/64-PCI board types.
1570 */
1571
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001572static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001574 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001575 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 int handled = 0;
1577
1578 while (inb(brdp->ioctrl) & 0x1) {
1579 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001580 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 ioaddr = brdp->bnkstataddr[bnknr];
1582 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1583 panelp = brdp->bnk2panel[bnknr];
1584 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1585 }
1586 }
1587 }
1588
1589 return handled;
1590}
1591
1592/*****************************************************************************/
1593
1594/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 * Initialize all the ports on a panel.
1596 */
1597
Jiri Slaby705c1862006-12-08 02:39:11 -08001598static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001600 struct stlport *portp;
1601 unsigned int i;
1602 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
Jiri Slabya0564e12006-12-08 02:38:37 -08001604 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 chipmask = stl_panelinit(brdp, panelp);
1607
1608/*
1609 * All UART's are initialized (if found!). Now go through and setup
1610 * each ports data structures.
1611 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001612 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001613 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001614 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001616 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 break;
1618 }
Alan Coxd18a7502008-10-13 10:40:07 +01001619 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001620 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 portp->magic = STL_PORTMAGIC;
1622 portp->portnr = i;
1623 portp->brdnr = panelp->brdnr;
1624 portp->panelnr = panelp->panelnr;
1625 portp->uartp = panelp->uartp;
1626 portp->clk = brdp->clk;
1627 portp->baud_base = STL_BAUDBASE;
1628 portp->close_delay = STL_CLOSEDELAY;
1629 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001630 init_waitqueue_head(&portp->port.open_wait);
1631 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 portp->stats.brd = portp->brdnr;
1633 portp->stats.panel = portp->panelnr;
1634 portp->stats.port = portp->portnr;
1635 panelp->ports[i] = portp;
1636 stl_portinit(brdp, panelp, portp);
1637 }
1638
Jiri Slabyc62429d2006-12-08 02:39:14 -08001639 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640}
1641
Jiri Slaby3b85b342006-12-08 02:39:10 -08001642static void stl_cleanup_panels(struct stlbrd *brdp)
1643{
1644 struct stlpanel *panelp;
1645 struct stlport *portp;
1646 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001647 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001648
1649 for (j = 0; j < STL_MAXPANELS; j++) {
1650 panelp = brdp->panels[j];
1651 if (panelp == NULL)
1652 continue;
1653 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1654 portp = panelp->ports[k];
1655 if (portp == NULL)
1656 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001657 tty = tty_port_tty_get(&portp->port);
1658 if (tty != NULL) {
1659 stl_hangup(tty);
1660 tty_kref_put(tty);
1661 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001662 kfree(portp->tx.buf);
1663 kfree(portp);
1664 }
1665 kfree(panelp);
1666 }
1667}
1668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669/*****************************************************************************/
1670
1671/*
1672 * Try to find and initialize an EasyIO board.
1673 */
1674
Jiri Slaby705c1862006-12-08 02:39:11 -08001675static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001677 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 unsigned int status;
1679 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001680 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
Jiri Slabya0564e12006-12-08 02:38:37 -08001682 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 brdp->ioctrl = brdp->ioaddr1 + 1;
1685 brdp->iostatus = brdp->ioaddr1 + 2;
1686
1687 status = inb(brdp->iostatus);
1688 if ((status & EIO_IDBITMASK) == EIO_MK3)
1689 brdp->ioctrl++;
1690
1691/*
1692 * Handle board specific stuff now. The real difference is PCI
1693 * or not PCI.
1694 */
1695 if (brdp->brdtype == BRD_EASYIOPCI) {
1696 brdp->iosize1 = 0x80;
1697 brdp->iosize2 = 0x80;
1698 name = "serial(EIO-PCI)";
1699 outb(0x41, (brdp->ioaddr2 + 0x4c));
1700 } else {
1701 brdp->iosize1 = 8;
1702 name = "serial(EIO)";
1703 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1704 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1705 printk("STALLION: invalid irq=%d for brd=%d\n",
1706 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001707 retval = -EINVAL;
1708 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 }
1710 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1711 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1712 brdp->ioctrl);
1713 }
1714
Jiri Slaby3b85b342006-12-08 02:39:10 -08001715 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1717 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1718 "%x conflicts with another device\n", brdp->brdnr,
1719 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001720 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 }
1722
1723 if (brdp->iosize2 > 0)
1724 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1725 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1726 "address %x conflicts with another device\n",
1727 brdp->brdnr, brdp->ioaddr2);
1728 printk(KERN_WARNING "STALLION: Warning, also "
1729 "releasing board %d I/O address %x \n",
1730 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001731 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 }
1733
1734/*
1735 * Everything looks OK, so let's go ahead and probe for the hardware.
1736 */
1737 brdp->clk = CD1400_CLK;
1738 brdp->isr = stl_eiointr;
1739
Jiri Slaby3b85b342006-12-08 02:39:10 -08001740 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 switch (status & EIO_IDBITMASK) {
1742 case EIO_8PORTM:
1743 brdp->clk = CD1400_CLK8M;
1744 /* fall thru */
1745 case EIO_8PORTRS:
1746 case EIO_8PORTDI:
1747 brdp->nrports = 8;
1748 break;
1749 case EIO_4PORTRS:
1750 brdp->nrports = 4;
1751 break;
1752 case EIO_MK3:
1753 switch (status & EIO_BRDMASK) {
1754 case ID_BRD4:
1755 brdp->nrports = 4;
1756 break;
1757 case ID_BRD8:
1758 brdp->nrports = 8;
1759 break;
1760 case ID_BRD16:
1761 brdp->nrports = 16;
1762 break;
1763 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001764 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 }
1766 break;
1767 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001768 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 }
1770
1771/*
1772 * We have verified that the board is actually present, so now we
1773 * can complete the setup.
1774 */
1775
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001776 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001777 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001779 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001780 retval = -ENOMEM;
1781 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 panelp->magic = STL_PANELMAGIC;
1785 panelp->brdnr = brdp->brdnr;
1786 panelp->panelnr = 0;
1787 panelp->nrports = brdp->nrports;
1788 panelp->iobase = brdp->ioaddr1;
1789 panelp->hwid = status;
1790 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001791 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 panelp->isr = stl_sc26198intr;
1793 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001794 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 panelp->isr = stl_cd1400eiointr;
1796 }
1797
1798 brdp->panels[0] = panelp;
1799 brdp->nrpanels = 1;
1800 brdp->state |= BRD_FOUND;
1801 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001802 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 printk("STALLION: failed to register interrupt "
1804 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001805 retval = -ENODEV;
1806 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001808
1809 return 0;
1810err_fr:
1811 stl_cleanup_panels(brdp);
1812err_rel2:
1813 if (brdp->iosize2 > 0)
1814 release_region(brdp->ioaddr2, brdp->iosize2);
1815err_rel1:
1816 release_region(brdp->ioaddr1, brdp->iosize1);
1817err:
1818 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819}
1820
1821/*****************************************************************************/
1822
1823/*
1824 * Try to find an ECH board and initialize it. This code is capable of
1825 * dealing with all types of ECH board.
1826 */
1827
Jiri Slaby705c1862006-12-08 02:39:11 -08001828static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001830 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001831 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1832 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 char *name;
1834
Jiri Slabya0564e12006-12-08 02:38:37 -08001835 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 status = 0;
1838 conflict = 0;
1839
1840/*
1841 * Set up the initial board register contents for boards. This varies a
1842 * bit between the different board types. So we need to handle each
1843 * separately. Also do a check that the supplied IRQ is good.
1844 */
1845 switch (brdp->brdtype) {
1846
1847 case BRD_ECH:
1848 brdp->isr = stl_echatintr;
1849 brdp->ioctrl = brdp->ioaddr1 + 1;
1850 brdp->iostatus = brdp->ioaddr1 + 1;
1851 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001852 if ((status & ECH_IDBITMASK) != ECH_ID) {
1853 retval = -ENODEV;
1854 goto err;
1855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1857 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1858 printk("STALLION: invalid irq=%d for brd=%d\n",
1859 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001860 retval = -EINVAL;
1861 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 }
1863 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1864 status |= (stl_vecmap[brdp->irq] << 1);
1865 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1866 brdp->ioctrlval = ECH_INTENABLE |
1867 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001868 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1870 brdp->iosize1 = 2;
1871 brdp->iosize2 = 32;
1872 name = "serial(EC8/32)";
1873 outb(status, brdp->ioaddr1);
1874 break;
1875
1876 case BRD_ECHMC:
1877 brdp->isr = stl_echmcaintr;
1878 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1879 brdp->iostatus = brdp->ioctrl;
1880 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001881 if ((status & ECH_IDBITMASK) != ECH_ID) {
1882 retval = -ENODEV;
1883 goto err;
1884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1886 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1887 printk("STALLION: invalid irq=%d for brd=%d\n",
1888 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001889 retval = -EINVAL;
1890 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 }
1892 outb(ECHMC_BRDRESET, brdp->ioctrl);
1893 outb(ECHMC_INTENABLE, brdp->ioctrl);
1894 brdp->iosize1 = 64;
1895 name = "serial(EC8/32-MC)";
1896 break;
1897
1898 case BRD_ECHPCI:
1899 brdp->isr = stl_echpciintr;
1900 brdp->ioctrl = brdp->ioaddr1 + 2;
1901 brdp->iosize1 = 4;
1902 brdp->iosize2 = 8;
1903 name = "serial(EC8/32-PCI)";
1904 break;
1905
1906 case BRD_ECH64PCI:
1907 brdp->isr = stl_echpci64intr;
1908 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1909 outb(0x43, (brdp->ioaddr1 + 0x4c));
1910 brdp->iosize1 = 0x80;
1911 brdp->iosize2 = 0x80;
1912 name = "serial(EC8/64-PCI)";
1913 break;
1914
1915 default:
1916 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001917 retval = -EINVAL;
1918 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 }
1920
1921/*
1922 * Check boards for possible IO address conflicts and return fail status
1923 * if an IO conflict found.
1924 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001925 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1927 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1928 "%x conflicts with another device\n", brdp->brdnr,
1929 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001930 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 }
1932
1933 if (brdp->iosize2 > 0)
1934 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1935 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1936 "address %x conflicts with another device\n",
1937 brdp->brdnr, brdp->ioaddr2);
1938 printk(KERN_WARNING "STALLION: Warning, also "
1939 "releasing board %d I/O address %x \n",
1940 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001941 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 }
1943
1944/*
1945 * Scan through the secondary io address space looking for panels.
1946 * As we find'em allocate and initialize panel structures for each.
1947 */
1948 brdp->clk = CD1400_CLK;
1949 brdp->hwid = status;
1950
1951 ioaddr = brdp->ioaddr2;
1952 banknr = 0;
1953 panelnr = 0;
1954 nxtid = 0;
1955
Jiri Slabyc62429d2006-12-08 02:39:14 -08001956 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 if (brdp->brdtype == BRD_ECHPCI) {
1958 outb(nxtid, brdp->ioctrl);
1959 ioaddr = brdp->ioaddr2;
1960 }
1961 status = inb(ioaddr + ECH_PNLSTATUS);
1962 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07001963 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001964 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001965 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001967 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07001968 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001969 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 panelp->magic = STL_PANELMAGIC;
1972 panelp->brdnr = brdp->brdnr;
1973 panelp->panelnr = panelnr;
1974 panelp->iobase = ioaddr;
1975 panelp->pagenr = nxtid;
1976 panelp->hwid = status;
1977 brdp->bnk2panel[banknr] = panelp;
1978 brdp->bnkpageaddr[banknr] = nxtid;
1979 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
1980
1981 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001982 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 panelp->isr = stl_sc26198intr;
1984 if (status & ECH_PNL16PORT) {
1985 panelp->nrports = 16;
1986 brdp->bnk2panel[banknr] = panelp;
1987 brdp->bnkpageaddr[banknr] = nxtid;
1988 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
1989 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001990 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001993 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 panelp->isr = stl_cd1400echintr;
1995 if (status & ECH_PNL16PORT) {
1996 panelp->nrports = 16;
1997 panelp->ackmask = 0x80;
1998 if (brdp->brdtype != BRD_ECHPCI)
1999 ioaddr += EREG_BANKSIZE;
2000 brdp->bnk2panel[banknr] = panelp;
2001 brdp->bnkpageaddr[banknr] = ++nxtid;
2002 brdp->bnkstataddr[banknr++] = ioaddr +
2003 ECH_PNLSTATUS;
2004 } else {
2005 panelp->nrports = 8;
2006 panelp->ackmask = 0xc0;
2007 }
2008 }
2009
2010 nxtid++;
2011 ioaddr += EREG_BANKSIZE;
2012 brdp->nrports += panelp->nrports;
2013 brdp->panels[panelnr++] = panelp;
2014 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002015 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2016 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002017 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 }
2020
2021 brdp->nrpanels = panelnr;
2022 brdp->nrbnks = banknr;
2023 if (brdp->brdtype == BRD_ECH)
2024 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2025
2026 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002027 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 printk("STALLION: failed to register interrupt "
2029 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002030 retval = -ENODEV;
2031 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 }
2033
Jiri Slaby3b85b342006-12-08 02:39:10 -08002034 return 0;
2035err_fr:
2036 stl_cleanup_panels(brdp);
2037 if (brdp->iosize2 > 0)
2038 release_region(brdp->ioaddr2, brdp->iosize2);
2039err_rel1:
2040 release_region(brdp->ioaddr1, brdp->iosize1);
2041err:
2042 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
2045/*****************************************************************************/
2046
2047/*
2048 * Initialize and configure the specified board.
2049 * Scan through all the boards in the configuration and see what we
2050 * can find. Handle EIO and the ECH boards a little differently here
2051 * since the initial search and setup is very different.
2052 */
2053
Jiri Slaby705c1862006-12-08 02:39:11 -08002054static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002056 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057
Jiri Slabya0564e12006-12-08 02:38:37 -08002058 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
2060 switch (brdp->brdtype) {
2061 case BRD_EASYIO:
2062 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002063 retval = stl_initeio(brdp);
2064 if (retval)
2065 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 break;
2067 case BRD_ECH:
2068 case BRD_ECHMC:
2069 case BRD_ECHPCI:
2070 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002071 retval = stl_initech(brdp);
2072 if (retval)
2073 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 break;
2075 default:
2076 printk("STALLION: board=%d is unknown board type=%d\n",
2077 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002078 retval = -ENODEV;
2079 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 }
2081
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 if ((brdp->state & BRD_FOUND) == 0) {
2083 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2084 stl_brdnames[brdp->brdtype], brdp->brdnr,
2085 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002086 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 }
2088
Jiri Slabyc62429d2006-12-08 02:39:14 -08002089 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002090 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 stl_initports(brdp, brdp->panels[i]);
2092
2093 printk("STALLION: %s found, board=%d io=%x irq=%d "
2094 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2095 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2096 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002097
2098 return 0;
2099err_free:
2100 free_irq(brdp->irq, brdp);
2101
2102 stl_cleanup_panels(brdp);
2103
2104 release_region(brdp->ioaddr1, brdp->iosize1);
2105 if (brdp->iosize2 > 0)
2106 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002107err:
2108 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109}
2110
2111/*****************************************************************************/
2112
2113/*
2114 * Find the next available board number that is free.
2115 */
2116
Jiri Slaby705c1862006-12-08 02:39:11 -08002117static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002119 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
Jiri Slabyc62429d2006-12-08 02:39:14 -08002121 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002122 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 if (i >= stl_nrbrds)
2124 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002125 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002127
2128 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
2131/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132/*
2133 * We have a Stallion board. Allocate a board structure and
2134 * initialize it. Read its IO and IRQ resources from PCI
2135 * configuration space.
2136 */
2137
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002138static int __devinit stl_pciprobe(struct pci_dev *pdev,
2139 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002141 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002142 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002143 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002145 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002146 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002147
Jiri Slaby3b85b342006-12-08 02:39:10 -08002148 retval = pci_enable_device(pdev);
2149 if (retval)
2150 goto err;
2151 brdp = stl_allocbrd();
2152 if (brdp == NULL) {
2153 retval = -ENOMEM;
2154 goto err;
2155 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002156 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002157 brdnr = stl_getbrdnr();
2158 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002159 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002161 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002162 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002163 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002165 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002166 stl_brds[brdp->brdnr] = brdp;
2167 mutex_unlock(&stl_brdslock);
2168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002170 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
2172/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 * We have all resources from the board, so let's setup the actual
2174 * board structure now.
2175 */
2176 switch (brdtype) {
2177 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002178 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2179 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 break;
2181 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002182 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2183 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 break;
2185 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002186 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2187 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 break;
2189 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002190 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 break;
2192 }
2193
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002194 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002195 retval = stl_brdinit(brdp);
2196 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002197 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002199 pci_set_drvdata(pdev, brdp);
2200
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002201 for (i = 0; i < brdp->nrports; i++)
2202 tty_register_device(stl_serial,
2203 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2204
Jiri Slaby3b85b342006-12-08 02:39:10 -08002205 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002206err_null:
2207 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002208err_fr:
2209 kfree(brdp);
2210err:
2211 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212}
2213
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002214static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002216 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002217 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002219 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002221 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002223 release_region(brdp->ioaddr1, brdp->iosize1);
2224 if (brdp->iosize2 > 0)
2225 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002227 for (i = 0; i < brdp->nrports; i++)
2228 tty_unregister_device(stl_serial,
2229 brdp->brdnr * STL_MAXPORTS + i);
2230
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002231 stl_brds[brdp->brdnr] = NULL;
2232 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233}
2234
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002235static struct pci_driver stl_pcidriver = {
2236 .name = "stallion",
2237 .id_table = stl_pcibrds,
2238 .probe = stl_pciprobe,
2239 .remove = __devexit_p(stl_pciremove)
2240};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
2242/*****************************************************************************/
2243
2244/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 * Return the board stats structure to user app.
2246 */
2247
2248static int stl_getbrdstats(combrd_t __user *bp)
2249{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002250 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002251 struct stlbrd *brdp;
2252 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002253 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
2255 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2256 return -EFAULT;
2257 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002258 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002260 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002261 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 memset(&stl_brdstats, 0, sizeof(combrd_t));
2264 stl_brdstats.brd = brdp->brdnr;
2265 stl_brdstats.type = brdp->brdtype;
2266 stl_brdstats.hwid = brdp->hwid;
2267 stl_brdstats.state = brdp->state;
2268 stl_brdstats.ioaddr = brdp->ioaddr1;
2269 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2270 stl_brdstats.irq = brdp->irq;
2271 stl_brdstats.nrpanels = brdp->nrpanels;
2272 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002273 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 panelp = brdp->panels[i];
2275 stl_brdstats.panels[i].panel = i;
2276 stl_brdstats.panels[i].hwid = panelp->hwid;
2277 stl_brdstats.panels[i].nrports = panelp->nrports;
2278 }
2279
2280 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2281}
2282
2283/*****************************************************************************/
2284
2285/*
2286 * Resolve the referenced port number into a port struct pointer.
2287 */
2288
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002289static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002291 struct stlbrd *brdp;
2292 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
Jiri Slabyc62429d2006-12-08 02:39:14 -08002294 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2295 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002297 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002298 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002299 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002300 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002302 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002303 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002304 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002305 return NULL;
2306 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307}
2308
2309/*****************************************************************************/
2310
2311/*
2312 * Return the port stats structure to user app. A NULL port struct
2313 * pointer passed in means that we need to find out from the app
2314 * what port to get stats for (used through board control device).
2315 */
2316
Alan Coxd18a7502008-10-13 10:40:07 +01002317static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002319 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 unsigned char *head, *tail;
2321 unsigned long flags;
2322
2323 if (!portp) {
2324 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2325 return -EFAULT;
2326 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2327 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002328 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002329 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 }
2331
Alan Coxb4eda9c2010-06-01 22:52:41 +02002332 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002334 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 portp->stats.hwid = portp->hwid;
2336
2337 portp->stats.ttystate = 0;
2338 portp->stats.cflags = 0;
2339 portp->stats.iflags = 0;
2340 portp->stats.oflags = 0;
2341 portp->stats.lflags = 0;
2342 portp->stats.rxbuffered = 0;
2343
Alan Coxb65b5b52006-06-27 02:54:05 -07002344 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002345 if (tty != NULL && portp->port.tty == tty) {
2346 portp->stats.ttystate = tty->flags;
2347 /* No longer available as a statistic */
2348 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2349 if (tty->termios != NULL) {
2350 portp->stats.cflags = tty->termios->c_cflag;
2351 portp->stats.iflags = tty->termios->c_iflag;
2352 portp->stats.oflags = tty->termios->c_oflag;
2353 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 }
Alan Coxd18a7502008-10-13 10:40:07 +01002355 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002356 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357
2358 head = portp->tx.head;
2359 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002360 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2361 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
2363 portp->stats.signals = (unsigned long) stl_getsignals(portp);
Alan Coxb4eda9c2010-06-01 22:52:41 +02002364 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365
2366 return copy_to_user(cp, &portp->stats,
2367 sizeof(comstats_t)) ? -EFAULT : 0;
2368}
2369
2370/*****************************************************************************/
2371
2372/*
2373 * Clear the port stats structure. We also return it zeroed out...
2374 */
2375
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002376static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002378 comstats_t stl_comstats;
2379
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 if (!portp) {
2381 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2382 return -EFAULT;
2383 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2384 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002385 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002386 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
2388
Alan Coxb4eda9c2010-06-01 22:52:41 +02002389 mutex_lock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 memset(&portp->stats, 0, sizeof(comstats_t));
2391 portp->stats.brd = portp->brdnr;
2392 portp->stats.panel = portp->panelnr;
2393 portp->stats.port = portp->portnr;
Alan Coxb4eda9c2010-06-01 22:52:41 +02002394 mutex_unlock(&portp->port.mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 return copy_to_user(cp, &portp->stats,
2396 sizeof(comstats_t)) ? -EFAULT : 0;
2397}
2398
2399/*****************************************************************************/
2400
2401/*
2402 * Return the entire driver ports structure to a user app.
2403 */
2404
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002405static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002407 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002408 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002410 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411 return -EFAULT;
2412 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2413 stl_dummyport.portnr);
2414 if (!portp)
2415 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002416 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417}
2418
2419/*****************************************************************************/
2420
2421/*
2422 * Return the entire driver board structure to a user app.
2423 */
2424
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002425static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002427 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002428 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002430 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002432 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 return -ENODEV;
2434 brdp = stl_brds[stl_dummybrd.brdnr];
2435 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002436 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002437 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438}
2439
2440/*****************************************************************************/
2441
2442/*
2443 * The "staliomem" device is also required to do some special operations
2444 * on the board and/or ports. In this driver it is mostly used for stats
2445 * collection.
2446 */
2447
Alan Cox894cb912009-10-13 16:34:15 +01002448static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449{
2450 int brdnr, rc;
2451 void __user *argp = (void __user *)arg;
2452
Alan Cox894cb912009-10-13 16:34:15 +01002453 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
Alan Cox894cb912009-10-13 16:34:15 +01002455 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002457 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 rc = 0;
2459
2460 switch (cmd) {
2461 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002462 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 break;
2464 case COM_CLRPORTSTATS:
2465 rc = stl_clrportstats(NULL, argp);
2466 break;
2467 case COM_GETBRDSTATS:
2468 rc = stl_getbrdstats(argp);
2469 break;
2470 case COM_READPORT:
2471 rc = stl_getportstruct(argp);
2472 break;
2473 case COM_READBOARD:
2474 rc = stl_getbrdstruct(argp);
2475 break;
2476 default:
2477 rc = -ENOIOCTLCMD;
2478 break;
2479 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002480 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481}
2482
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002483static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 .open = stl_open,
2485 .close = stl_close,
2486 .write = stl_write,
2487 .put_char = stl_putchar,
2488 .flush_chars = stl_flushchars,
2489 .write_room = stl_writeroom,
2490 .chars_in_buffer = stl_charsinbuffer,
2491 .ioctl = stl_ioctl,
2492 .set_termios = stl_settermios,
2493 .throttle = stl_throttle,
2494 .unthrottle = stl_unthrottle,
2495 .stop = stl_stop,
2496 .start = stl_start,
2497 .hangup = stl_hangup,
2498 .flush_buffer = stl_flushbuffer,
2499 .break_ctl = stl_breakctl,
2500 .wait_until_sent = stl_waituntilsent,
2501 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 .tiocmget = stl_tiocmget,
2503 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002504 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505};
2506
Alan Cox31f35932009-01-02 13:45:05 +00002507static const struct tty_port_operations stl_port_ops = {
2508 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002509 .dtr_rts = stl_dtr_rts,
Alan Cox047e9652009-11-30 13:17:03 +00002510 .activate = stl_activate,
2511 .shutdown = stl_shutdown,
Alan Cox31f35932009-01-02 13:45:05 +00002512};
2513
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515/* CD1400 HARDWARE FUNCTIONS */
2516/*****************************************************************************/
2517
2518/*
2519 * These functions get/set/update the registers of the cd1400 UARTs.
2520 * Access to the cd1400 registers is via an address/data io port pair.
2521 * (Maybe should make this inline...)
2522 */
2523
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002524static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525{
2526 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002527 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528}
2529
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002530static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002532 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 outb(value, portp->ioaddr + EREG_DATA);
2534}
2535
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002536static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002538 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 if (inb(portp->ioaddr + EREG_DATA) != value) {
2540 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002541 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002543 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544}
2545
2546/*****************************************************************************/
2547
2548/*
2549 * Inbitialize the UARTs in a panel. We don't care what sort of board
2550 * these ports are on - since the port io registers are almost
2551 * identical when dealing with ports.
2552 */
2553
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002554static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555{
2556 unsigned int gfrcr;
2557 int chipmask, i, j;
2558 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002559 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
Jiri Slabya0564e12006-12-08 02:38:37 -08002561 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Alan Coxb65b5b52006-06-27 02:54:05 -07002563 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 BRDENABLE(panelp->brdnr, panelp->pagenr);
2565
2566/*
2567 * Check that each chip is present and started up OK.
2568 */
2569 chipmask = 0;
2570 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002571 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 if (brdp->brdtype == BRD_ECHPCI) {
2573 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2574 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002575 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 uartaddr = (i & 0x01) ? 0x080 : 0;
2578 outb((GFRCR + uartaddr), ioaddr);
2579 outb(0, (ioaddr + EREG_DATA));
2580 outb((CCR + uartaddr), ioaddr);
2581 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2582 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2583 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002584 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2586 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002587
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2589 printk("STALLION: cd1400 not responding, "
2590 "brd=%d panel=%d chip=%d\n",
2591 panelp->brdnr, panelp->panelnr, i);
2592 continue;
2593 }
2594 chipmask |= (0x1 << i);
2595 outb((PPR + uartaddr), ioaddr);
2596 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2597 }
2598
2599 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002600 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002601 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602}
2603
2604/*****************************************************************************/
2605
2606/*
2607 * Initialize hardware specific port registers.
2608 */
2609
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002610static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611{
Alan Coxb65b5b52006-06-27 02:54:05 -07002612 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002613 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2614 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
Jiri Slaby615e4a72006-12-08 02:38:38 -08002616 if ((brdp == NULL) || (panelp == NULL) ||
2617 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 return;
2619
Alan Coxb65b5b52006-06-27 02:54:05 -07002620 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2622 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2623 portp->uartaddr = (portp->portnr & 0x04) << 5;
2624 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2625
2626 BRDENABLE(portp->brdnr, portp->pagenr);
2627 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2628 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2629 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2630 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002631 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632}
2633
2634/*****************************************************************************/
2635
2636/*
2637 * Wait for the command register to be ready. We will poll this,
2638 * since it won't usually take too long to be ready.
2639 */
2640
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002641static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642{
2643 int i;
2644
Jiri Slabyc62429d2006-12-08 02:39:14 -08002645 for (i = 0; i < CCR_MAXWAIT; i++)
2646 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
2649 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2650 portp->portnr, portp->panelnr, portp->brdnr);
2651}
2652
2653/*****************************************************************************/
2654
2655/*
2656 * Set up the cd1400 registers for a port based on the termios port
2657 * settings.
2658 */
2659
Alan Cox606d0992006-12-08 02:38:45 -08002660static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002662 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 unsigned long flags;
2664 unsigned int clkdiv, baudrate;
2665 unsigned char cor1, cor2, cor3;
2666 unsigned char cor4, cor5, ccr;
2667 unsigned char srer, sreron, sreroff;
2668 unsigned char mcor1, mcor2, rtpr;
2669 unsigned char clk, div;
2670
2671 cor1 = 0;
2672 cor2 = 0;
2673 cor3 = 0;
2674 cor4 = 0;
2675 cor5 = 0;
2676 ccr = 0;
2677 rtpr = 0;
2678 clk = 0;
2679 div = 0;
2680 mcor1 = 0;
2681 mcor2 = 0;
2682 sreron = 0;
2683 sreroff = 0;
2684
2685 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002686 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 return;
2688
2689/*
2690 * Set up the RX char ignore mask with those RX error types we
2691 * can ignore. We can get the cd1400 to help us out a little here,
2692 * it will ignore parity errors and breaks for us.
2693 */
2694 portp->rxignoremsk = 0;
2695 if (tiosp->c_iflag & IGNPAR) {
2696 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2697 cor1 |= COR1_PARIGNORE;
2698 }
2699 if (tiosp->c_iflag & IGNBRK) {
2700 portp->rxignoremsk |= ST_BREAK;
2701 cor4 |= COR4_IGNBRK;
2702 }
2703
2704 portp->rxmarkmsk = ST_OVERRUN;
2705 if (tiosp->c_iflag & (INPCK | PARMRK))
2706 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2707 if (tiosp->c_iflag & BRKINT)
2708 portp->rxmarkmsk |= ST_BREAK;
2709
2710/*
2711 * Go through the char size, parity and stop bits and set all the
2712 * option register appropriately.
2713 */
2714 switch (tiosp->c_cflag & CSIZE) {
2715 case CS5:
2716 cor1 |= COR1_CHL5;
2717 break;
2718 case CS6:
2719 cor1 |= COR1_CHL6;
2720 break;
2721 case CS7:
2722 cor1 |= COR1_CHL7;
2723 break;
2724 default:
2725 cor1 |= COR1_CHL8;
2726 break;
2727 }
2728
2729 if (tiosp->c_cflag & CSTOPB)
2730 cor1 |= COR1_STOP2;
2731 else
2732 cor1 |= COR1_STOP1;
2733
2734 if (tiosp->c_cflag & PARENB) {
2735 if (tiosp->c_cflag & PARODD)
2736 cor1 |= (COR1_PARENB | COR1_PARODD);
2737 else
2738 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2739 } else {
2740 cor1 |= COR1_PARNONE;
2741 }
2742
2743/*
2744 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2745 * space for hardware flow control and the like. This should be set to
2746 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2747 * really be based on VTIME.
2748 */
2749 cor3 |= FIFO_RXTHRESHOLD;
2750 rtpr = 2;
2751
2752/*
2753 * Calculate the baud rate timers. For now we will just assume that
2754 * the input and output baud are the same. Could have used a baud
2755 * table here, but this way we can generate virtually any baud rate
2756 * we like!
2757 */
2758 baudrate = tiosp->c_cflag & CBAUD;
2759 if (baudrate & CBAUDEX) {
2760 baudrate &= ~CBAUDEX;
2761 if ((baudrate < 1) || (baudrate > 4))
2762 tiosp->c_cflag &= ~CBAUDEX;
2763 else
2764 baudrate += 15;
2765 }
2766 baudrate = stl_baudrates[baudrate];
2767 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002768 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002770 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002772 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002774 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002776 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 baudrate = (portp->baud_base / portp->custom_divisor);
2778 }
2779 if (baudrate > STL_CD1400MAXBAUD)
2780 baudrate = STL_CD1400MAXBAUD;
2781
2782 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002783 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2784 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 if (clkdiv < 0x100)
2786 break;
2787 }
2788 div = (unsigned char) clkdiv;
2789 }
2790
2791/*
2792 * Check what form of modem signaling is required and set it up.
2793 */
2794 if ((tiosp->c_cflag & CLOCAL) == 0) {
2795 mcor1 |= MCOR1_DCD;
2796 mcor2 |= MCOR2_DCD;
2797 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002798 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002799 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002800 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
2802/*
2803 * Setup cd1400 enhanced modes if we can. In particular we want to
2804 * handle as much of the flow control as possible automatically. As
2805 * well as saving a few CPU cycles it will also greatly improve flow
2806 * control reliability.
2807 */
2808 if (tiosp->c_iflag & IXON) {
2809 cor2 |= COR2_TXIBE;
2810 cor3 |= COR3_SCD12;
2811 if (tiosp->c_iflag & IXANY)
2812 cor2 |= COR2_IXM;
2813 }
2814
2815 if (tiosp->c_cflag & CRTSCTS) {
2816 cor2 |= COR2_CTSAE;
2817 mcor1 |= FIFO_RTSTHRESHOLD;
2818 }
2819
2820/*
2821 * All cd1400 register values calculated so go through and set
2822 * them all up.
2823 */
2824
Jiri Slabya0564e12006-12-08 02:38:37 -08002825 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002827 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002829 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002831 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2832 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2834 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835
Alan Coxb65b5b52006-06-27 02:54:05 -07002836 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 BRDENABLE(portp->brdnr, portp->pagenr);
2838 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2839 srer = stl_cd1400getreg(portp, SRER);
2840 stl_cd1400setreg(portp, SRER, 0);
2841 if (stl_cd1400updatereg(portp, COR1, cor1))
2842 ccr = 1;
2843 if (stl_cd1400updatereg(portp, COR2, cor2))
2844 ccr = 1;
2845 if (stl_cd1400updatereg(portp, COR3, cor3))
2846 ccr = 1;
2847 if (ccr) {
2848 stl_cd1400ccrwait(portp);
2849 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2850 }
2851 stl_cd1400setreg(portp, COR4, cor4);
2852 stl_cd1400setreg(portp, COR5, cor5);
2853 stl_cd1400setreg(portp, MCOR1, mcor1);
2854 stl_cd1400setreg(portp, MCOR2, mcor2);
2855 if (baudrate > 0) {
2856 stl_cd1400setreg(portp, TCOR, clk);
2857 stl_cd1400setreg(portp, TBPR, div);
2858 stl_cd1400setreg(portp, RCOR, clk);
2859 stl_cd1400setreg(portp, RBPR, div);
2860 }
2861 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2862 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2863 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2864 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2865 stl_cd1400setreg(portp, RTPR, rtpr);
2866 mcor1 = stl_cd1400getreg(portp, MSVR1);
2867 if (mcor1 & MSVR1_DCD)
2868 portp->sigs |= TIOCM_CD;
2869 else
2870 portp->sigs &= ~TIOCM_CD;
2871 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2872 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002873 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874}
2875
2876/*****************************************************************************/
2877
2878/*
2879 * Set the state of the DTR and RTS signals.
2880 */
2881
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002882static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883{
2884 unsigned char msvr1, msvr2;
2885 unsigned long flags;
2886
Jiri Slabya0564e12006-12-08 02:38:37 -08002887 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2888 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
2890 msvr1 = 0;
2891 msvr2 = 0;
2892 if (dtr > 0)
2893 msvr1 = MSVR1_DTR;
2894 if (rts > 0)
2895 msvr2 = MSVR2_RTS;
2896
Alan Coxb65b5b52006-06-27 02:54:05 -07002897 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 BRDENABLE(portp->brdnr, portp->pagenr);
2899 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2900 if (rts >= 0)
2901 stl_cd1400setreg(portp, MSVR2, msvr2);
2902 if (dtr >= 0)
2903 stl_cd1400setreg(portp, MSVR1, msvr1);
2904 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002905 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906}
2907
2908/*****************************************************************************/
2909
2910/*
2911 * Return the state of the signals.
2912 */
2913
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002914static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915{
2916 unsigned char msvr1, msvr2;
2917 unsigned long flags;
2918 int sigs;
2919
Jiri Slabya0564e12006-12-08 02:38:37 -08002920 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Alan Coxb65b5b52006-06-27 02:54:05 -07002922 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923 BRDENABLE(portp->brdnr, portp->pagenr);
2924 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2925 msvr1 = stl_cd1400getreg(portp, MSVR1);
2926 msvr2 = stl_cd1400getreg(portp, MSVR2);
2927 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002928 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
2930 sigs = 0;
2931 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2932 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2933 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2934 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2935#if 0
2936 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2937 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2938#else
2939 sigs |= TIOCM_DSR;
2940#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002941 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942}
2943
2944/*****************************************************************************/
2945
2946/*
2947 * Enable/Disable the Transmitter and/or Receiver.
2948 */
2949
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002950static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
2952 unsigned char ccr;
2953 unsigned long flags;
2954
Jiri Slabya0564e12006-12-08 02:38:37 -08002955 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2956
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 ccr = 0;
2958
2959 if (tx == 0)
2960 ccr |= CCR_TXDISABLE;
2961 else if (tx > 0)
2962 ccr |= CCR_TXENABLE;
2963 if (rx == 0)
2964 ccr |= CCR_RXDISABLE;
2965 else if (rx > 0)
2966 ccr |= CCR_RXENABLE;
2967
Alan Coxb65b5b52006-06-27 02:54:05 -07002968 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 BRDENABLE(portp->brdnr, portp->pagenr);
2970 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2971 stl_cd1400ccrwait(portp);
2972 stl_cd1400setreg(portp, CCR, ccr);
2973 stl_cd1400ccrwait(portp);
2974 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002975 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976}
2977
2978/*****************************************************************************/
2979
2980/*
2981 * Start/stop the Transmitter and/or Receiver.
2982 */
2983
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002984static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985{
2986 unsigned char sreron, sreroff;
2987 unsigned long flags;
2988
Jiri Slabya0564e12006-12-08 02:38:37 -08002989 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
2991 sreron = 0;
2992 sreroff = 0;
2993 if (tx == 0)
2994 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
2995 else if (tx == 1)
2996 sreron |= SRER_TXDATA;
2997 else if (tx >= 2)
2998 sreron |= SRER_TXEMPTY;
2999 if (rx == 0)
3000 sreroff |= SRER_RXDATA;
3001 else if (rx > 0)
3002 sreron |= SRER_RXDATA;
3003
Alan Coxb65b5b52006-06-27 02:54:05 -07003004 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 BRDENABLE(portp->brdnr, portp->pagenr);
3006 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3007 stl_cd1400setreg(portp, SRER,
3008 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3009 BRDDISABLE(portp->brdnr);
3010 if (tx > 0)
3011 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003012 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013}
3014
3015/*****************************************************************************/
3016
3017/*
3018 * Disable all interrupts from this port.
3019 */
3020
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003021static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022{
3023 unsigned long flags;
3024
Jiri Slabya0564e12006-12-08 02:38:37 -08003025 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3026
Alan Coxb65b5b52006-06-27 02:54:05 -07003027 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 BRDENABLE(portp->brdnr, portp->pagenr);
3029 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3030 stl_cd1400setreg(portp, SRER, 0);
3031 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003032 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033}
3034
3035/*****************************************************************************/
3036
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003037static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038{
3039 unsigned long flags;
3040
Jiri Slabya0564e12006-12-08 02:38:37 -08003041 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042
Alan Coxb65b5b52006-06-27 02:54:05 -07003043 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 BRDENABLE(portp->brdnr, portp->pagenr);
3045 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3046 stl_cd1400setreg(portp, SRER,
3047 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3048 SRER_TXEMPTY));
3049 BRDDISABLE(portp->brdnr);
3050 portp->brklen = len;
3051 if (len == 1)
3052 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003053 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054}
3055
3056/*****************************************************************************/
3057
3058/*
3059 * Take flow control actions...
3060 */
3061
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003062static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063{
3064 struct tty_struct *tty;
3065 unsigned long flags;
3066
Jiri Slabya0564e12006-12-08 02:38:37 -08003067 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068
Jiri Slaby615e4a72006-12-08 02:38:38 -08003069 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003071 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003072 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 return;
3074
Alan Coxb65b5b52006-06-27 02:54:05 -07003075 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 BRDENABLE(portp->brdnr, portp->pagenr);
3077 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3078
3079 if (state) {
3080 if (tty->termios->c_iflag & IXOFF) {
3081 stl_cd1400ccrwait(portp);
3082 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3083 portp->stats.rxxon++;
3084 stl_cd1400ccrwait(portp);
3085 }
3086/*
3087 * Question: should we return RTS to what it was before? It may
3088 * have been set by an ioctl... Suppose not, since if you have
3089 * hardware flow control set then it is pretty silly to go and
3090 * set the RTS line by hand.
3091 */
3092 if (tty->termios->c_cflag & CRTSCTS) {
3093 stl_cd1400setreg(portp, MCOR1,
3094 (stl_cd1400getreg(portp, MCOR1) |
3095 FIFO_RTSTHRESHOLD));
3096 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3097 portp->stats.rxrtson++;
3098 }
3099 } else {
3100 if (tty->termios->c_iflag & IXOFF) {
3101 stl_cd1400ccrwait(portp);
3102 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3103 portp->stats.rxxoff++;
3104 stl_cd1400ccrwait(portp);
3105 }
3106 if (tty->termios->c_cflag & CRTSCTS) {
3107 stl_cd1400setreg(portp, MCOR1,
3108 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3109 stl_cd1400setreg(portp, MSVR2, 0);
3110 portp->stats.rxrtsoff++;
3111 }
3112 }
3113
3114 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003115 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003116 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117}
3118
3119/*****************************************************************************/
3120
3121/*
3122 * Send a flow control character...
3123 */
3124
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003125static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126{
3127 struct tty_struct *tty;
3128 unsigned long flags;
3129
Jiri Slabya0564e12006-12-08 02:38:37 -08003130 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
Jiri Slaby615e4a72006-12-08 02:38:38 -08003132 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003134 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003135 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 return;
3137
Alan Coxb65b5b52006-06-27 02:54:05 -07003138 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 BRDENABLE(portp->brdnr, portp->pagenr);
3140 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3141 if (state) {
3142 stl_cd1400ccrwait(portp);
3143 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3144 portp->stats.rxxon++;
3145 stl_cd1400ccrwait(portp);
3146 } else {
3147 stl_cd1400ccrwait(portp);
3148 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3149 portp->stats.rxxoff++;
3150 stl_cd1400ccrwait(portp);
3151 }
3152 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003153 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003154 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155}
3156
3157/*****************************************************************************/
3158
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003159static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160{
3161 unsigned long flags;
3162
Jiri Slabya0564e12006-12-08 02:38:37 -08003163 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Jiri Slaby615e4a72006-12-08 02:38:38 -08003165 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 return;
3167
Alan Coxb65b5b52006-06-27 02:54:05 -07003168 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 BRDENABLE(portp->brdnr, portp->pagenr);
3170 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3171 stl_cd1400ccrwait(portp);
3172 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3173 stl_cd1400ccrwait(portp);
3174 portp->tx.tail = portp->tx.head;
3175 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003176 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177}
3178
3179/*****************************************************************************/
3180
3181/*
3182 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02003183 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 * transmission or not... This is easy for the cd1400, it accurately
3185 * maintains the busy port flag.
3186 */
3187
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003188static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189{
Jiri Slabya0564e12006-12-08 02:38:37 -08003190 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
Jiri Slaby615e4a72006-12-08 02:38:38 -08003192 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003193 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Jesper Juhl014c2542006-01-15 02:37:08 +01003195 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196}
3197
3198/*****************************************************************************/
3199
3200/*
3201 * Interrupt service routine for cd1400 EasyIO boards.
3202 */
3203
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003204static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205{
3206 unsigned char svrtype;
3207
Jiri Slabya0564e12006-12-08 02:38:37 -08003208 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209
Alan Coxb65b5b52006-06-27 02:54:05 -07003210 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 outb(SVRR, iobase);
3212 svrtype = inb(iobase + EREG_DATA);
3213 if (panelp->nrports > 4) {
3214 outb((SVRR + 0x80), iobase);
3215 svrtype |= inb(iobase + EREG_DATA);
3216 }
3217
3218 if (svrtype & SVRR_RX)
3219 stl_cd1400rxisr(panelp, iobase);
3220 else if (svrtype & SVRR_TX)
3221 stl_cd1400txisr(panelp, iobase);
3222 else if (svrtype & SVRR_MDM)
3223 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003224
3225 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226}
3227
3228/*****************************************************************************/
3229
3230/*
3231 * Interrupt service routine for cd1400 panels.
3232 */
3233
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003234static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
3236 unsigned char svrtype;
3237
Jiri Slabya0564e12006-12-08 02:38:37 -08003238 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239
3240 outb(SVRR, iobase);
3241 svrtype = inb(iobase + EREG_DATA);
3242 outb((SVRR + 0x80), iobase);
3243 svrtype |= inb(iobase + EREG_DATA);
3244 if (svrtype & SVRR_RX)
3245 stl_cd1400rxisr(panelp, iobase);
3246 else if (svrtype & SVRR_TX)
3247 stl_cd1400txisr(panelp, iobase);
3248 else if (svrtype & SVRR_MDM)
3249 stl_cd1400mdmisr(panelp, iobase);
3250}
3251
3252
3253/*****************************************************************************/
3254
3255/*
3256 * Unfortunately we need to handle breaks in the TX data stream, since
3257 * this is the only way to generate them on the cd1400.
3258 */
3259
Jiri Slaby60be4812006-12-08 02:38:40 -08003260static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261{
3262 if (portp->brklen == 1) {
3263 outb((COR2 + portp->uartaddr), ioaddr);
3264 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3265 (ioaddr + EREG_DATA));
3266 outb((TDR + portp->uartaddr), ioaddr);
3267 outb(ETC_CMD, (ioaddr + EREG_DATA));
3268 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3269 outb((SRER + portp->uartaddr), ioaddr);
3270 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3271 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003272 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 } else if (portp->brklen > 1) {
3274 outb((TDR + portp->uartaddr), ioaddr);
3275 outb(ETC_CMD, (ioaddr + EREG_DATA));
3276 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3277 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003278 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 } else {
3280 outb((COR2 + portp->uartaddr), ioaddr);
3281 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3282 (ioaddr + EREG_DATA));
3283 portp->brklen = 0;
3284 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003285 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286}
3287
3288/*****************************************************************************/
3289
3290/*
3291 * Transmit interrupt handler. This has gotta be fast! Handling TX
3292 * chars is pretty simple, stuff as many as possible from the TX buffer
3293 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3294 * are embedded as commands in the data stream. Oh no, had to use a goto!
3295 * This could be optimized more, will do when I get time...
3296 * In practice it is possible that interrupts are enabled but that the
3297 * port has been hung up. Need to handle not having any TX buffer here,
3298 * this is done by using the side effect that head and tail will also
3299 * be NULL if the buffer has been freed.
3300 */
3301
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003302static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003304 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 int len, stlen;
3306 char *head, *tail;
3307 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003308 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Jiri Slabya0564e12006-12-08 02:38:37 -08003310 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
3312 ioack = inb(ioaddr + EREG_TXACK);
3313 if (((ioack & panelp->ackmask) != 0) ||
3314 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3315 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3316 return;
3317 }
3318 portp = panelp->ports[(ioack >> 3)];
3319
3320/*
3321 * Unfortunately we need to handle breaks in the data stream, since
3322 * this is the only way to generate them on the cd1400. Do it now if
3323 * a break is to be sent.
3324 */
3325 if (portp->brklen != 0)
3326 if (stl_cd1400breakisr(portp, ioaddr))
3327 goto stl_txalldone;
3328
3329 head = portp->tx.head;
3330 tail = portp->tx.tail;
3331 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3332 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3333 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3334 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003335 tty = tty_port_tty_get(&portp->port);
3336 if (tty) {
3337 tty_wakeup(tty);
3338 tty_kref_put(tty);
3339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 }
3341
3342 if (len == 0) {
3343 outb((SRER + portp->uartaddr), ioaddr);
3344 srer = inb(ioaddr + EREG_DATA);
3345 if (srer & SRER_TXDATA) {
3346 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3347 } else {
3348 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3349 clear_bit(ASYI_TXBUSY, &portp->istate);
3350 }
3351 outb(srer, (ioaddr + EREG_DATA));
3352 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003353 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003355 stlen = min_t(unsigned int, len,
3356 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357 outb((TDR + portp->uartaddr), ioaddr);
3358 outsb((ioaddr + EREG_DATA), tail, stlen);
3359 len -= stlen;
3360 tail += stlen;
3361 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3362 tail = portp->tx.buf;
3363 if (len > 0) {
3364 outsb((ioaddr + EREG_DATA), tail, len);
3365 tail += len;
3366 }
3367 portp->tx.tail = tail;
3368 }
3369
3370stl_txalldone:
3371 outb((EOSRR + portp->uartaddr), ioaddr);
3372 outb(0, (ioaddr + EREG_DATA));
3373}
3374
3375/*****************************************************************************/
3376
3377/*
3378 * Receive character interrupt handler. Determine if we have good chars
3379 * or bad chars and then process appropriately. Good chars are easy
3380 * just shove the lot into the RX buffer and set all status byte to 0.
3381 * If a bad RX char then process as required. This routine needs to be
3382 * fast! In practice it is possible that we get an interrupt on a port
3383 * that is closed. This can happen on hangups - since they completely
3384 * shutdown a port not in user context. Need to handle this case.
3385 */
3386
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003387static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003389 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 struct tty_struct *tty;
3391 unsigned int ioack, len, buflen;
3392 unsigned char status;
3393 char ch;
3394
Jiri Slabya0564e12006-12-08 02:38:37 -08003395 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
3397 ioack = inb(ioaddr + EREG_RXACK);
3398 if ((ioack & panelp->ackmask) != 0) {
3399 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3400 return;
3401 }
3402 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003403 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
3405 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3406 outb((RDCR + portp->uartaddr), ioaddr);
3407 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003408 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003409 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 outb((RDSR + portp->uartaddr), ioaddr);
3411 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3412 portp->stats.rxlost += len;
3413 portp->stats.rxtotal += len;
3414 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003415 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003417 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003419 tty_prepare_flip_string(tty, &ptr, len);
3420 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 tty_schedule_flip(tty);
3422 portp->stats.rxtotal += len;
3423 }
3424 }
3425 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3426 outb((RDSR + portp->uartaddr), ioaddr);
3427 status = inb(ioaddr + EREG_DATA);
3428 ch = inb(ioaddr + EREG_DATA);
3429 if (status & ST_PARITY)
3430 portp->stats.rxparity++;
3431 if (status & ST_FRAMING)
3432 portp->stats.rxframing++;
3433 if (status & ST_OVERRUN)
3434 portp->stats.rxoverrun++;
3435 if (status & ST_BREAK)
3436 portp->stats.rxbreaks++;
3437 if (status & ST_SCHARMASK) {
3438 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3439 portp->stats.txxon++;
3440 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3441 portp->stats.txxoff++;
3442 goto stl_rxalldone;
3443 }
Alan Cox33f0f882006-01-09 20:54:13 -08003444 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 if (portp->rxmarkmsk & status) {
3446 if (status & ST_BREAK) {
3447 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003448 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 do_SAK(tty);
3450 BRDENABLE(portp->brdnr, portp->pagenr);
3451 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003452 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003454 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003456 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003458 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003460 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003462 tty_insert_flip_char(tty, ch, status);
3463 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 }
3465 } else {
3466 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003467 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 return;
3469 }
3470
3471stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003472 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 outb((EOSRR + portp->uartaddr), ioaddr);
3474 outb(0, (ioaddr + EREG_DATA));
3475}
3476
3477/*****************************************************************************/
3478
3479/*
3480 * Modem interrupt handler. The is called when the modem signal line
3481 * (DCD) has changed state. Leave most of the work to the off-level
3482 * processing routine.
3483 */
3484
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003485static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003487 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 unsigned int ioack;
3489 unsigned char misr;
3490
Jiri Slabya0564e12006-12-08 02:38:37 -08003491 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492
3493 ioack = inb(ioaddr + EREG_MDACK);
3494 if (((ioack & panelp->ackmask) != 0) ||
3495 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3496 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3497 return;
3498 }
3499 portp = panelp->ports[(ioack >> 3)];
3500
3501 outb((MISR + portp->uartaddr), ioaddr);
3502 misr = inb(ioaddr + EREG_DATA);
3503 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003504 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 portp->stats.modem++;
3506 }
3507
3508 outb((EOSRR + portp->uartaddr), ioaddr);
3509 outb(0, (ioaddr + EREG_DATA));
3510}
3511
3512/*****************************************************************************/
3513/* SC26198 HARDWARE FUNCTIONS */
3514/*****************************************************************************/
3515
3516/*
3517 * These functions get/set/update the registers of the sc26198 UARTs.
3518 * Access to the sc26198 registers is via an address/data io port pair.
3519 * (Maybe should make this inline...)
3520 */
3521
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003522static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523{
3524 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003525 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526}
3527
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003528static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529{
3530 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3531 outb(value, (portp->ioaddr + XP_DATA));
3532}
3533
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003534static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535{
3536 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3537 if (inb(portp->ioaddr + XP_DATA) != value) {
3538 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003539 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003541 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542}
3543
3544/*****************************************************************************/
3545
3546/*
3547 * Functions to get and set the sc26198 global registers.
3548 */
3549
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003550static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551{
3552 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003553 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554}
3555
3556#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003557static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558{
3559 outb(regnr, (portp->ioaddr + XP_ADDR));
3560 outb(value, (portp->ioaddr + XP_DATA));
3561}
3562#endif
3563
3564/*****************************************************************************/
3565
3566/*
3567 * Inbitialize the UARTs in a panel. We don't care what sort of board
3568 * these ports are on - since the port io registers are almost
3569 * identical when dealing with ports.
3570 */
3571
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003572static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573{
3574 int chipmask, i;
3575 int nrchips, ioaddr;
3576
Jiri Slabya0564e12006-12-08 02:38:37 -08003577 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 BRDENABLE(panelp->brdnr, panelp->pagenr);
3580
3581/*
3582 * Check that each chip is present and started up OK.
3583 */
3584 chipmask = 0;
3585 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3586 if (brdp->brdtype == BRD_ECHPCI)
3587 outb(panelp->pagenr, brdp->ioctrl);
3588
Jiri Slabyc62429d2006-12-08 02:39:14 -08003589 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 ioaddr = panelp->iobase + (i * 4);
3591 outb(SCCR, (ioaddr + XP_ADDR));
3592 outb(CR_RESETALL, (ioaddr + XP_DATA));
3593 outb(TSTR, (ioaddr + XP_ADDR));
3594 if (inb(ioaddr + XP_DATA) != 0) {
3595 printk("STALLION: sc26198 not responding, "
3596 "brd=%d panel=%d chip=%d\n",
3597 panelp->brdnr, panelp->panelnr, i);
3598 continue;
3599 }
3600 chipmask |= (0x1 << i);
3601 outb(GCCR, (ioaddr + XP_ADDR));
3602 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3603 outb(WDTRCR, (ioaddr + XP_ADDR));
3604 outb(0xff, (ioaddr + XP_DATA));
3605 }
3606
3607 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003608 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609}
3610
3611/*****************************************************************************/
3612
3613/*
3614 * Initialize hardware specific port registers.
3615 */
3616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003617static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618{
Jiri Slabya0564e12006-12-08 02:38:37 -08003619 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3620 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
Jiri Slaby615e4a72006-12-08 02:38:38 -08003622 if ((brdp == NULL) || (panelp == NULL) ||
3623 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 return;
3625
3626 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3627 portp->uartaddr = (portp->portnr & 0x07) << 4;
3628 portp->pagenr = panelp->pagenr;
3629 portp->hwid = 0x1;
3630
3631 BRDENABLE(portp->brdnr, portp->pagenr);
3632 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3633 BRDDISABLE(portp->brdnr);
3634}
3635
3636/*****************************************************************************/
3637
3638/*
3639 * Set up the sc26198 registers for a port based on the termios port
3640 * settings.
3641 */
3642
Alan Cox606d0992006-12-08 02:38:45 -08003643static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003645 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 unsigned long flags;
3647 unsigned int baudrate;
3648 unsigned char mr0, mr1, mr2, clk;
3649 unsigned char imron, imroff, iopr, ipr;
3650
3651 mr0 = 0;
3652 mr1 = 0;
3653 mr2 = 0;
3654 clk = 0;
3655 iopr = 0;
3656 imron = 0;
3657 imroff = 0;
3658
3659 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003660 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 return;
3662
3663/*
3664 * Set up the RX char ignore mask with those RX error types we
3665 * can ignore.
3666 */
3667 portp->rxignoremsk = 0;
3668 if (tiosp->c_iflag & IGNPAR)
3669 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3670 SR_RXOVERRUN);
3671 if (tiosp->c_iflag & IGNBRK)
3672 portp->rxignoremsk |= SR_RXBREAK;
3673
3674 portp->rxmarkmsk = SR_RXOVERRUN;
3675 if (tiosp->c_iflag & (INPCK | PARMRK))
3676 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3677 if (tiosp->c_iflag & BRKINT)
3678 portp->rxmarkmsk |= SR_RXBREAK;
3679
3680/*
3681 * Go through the char size, parity and stop bits and set all the
3682 * option register appropriately.
3683 */
3684 switch (tiosp->c_cflag & CSIZE) {
3685 case CS5:
3686 mr1 |= MR1_CS5;
3687 break;
3688 case CS6:
3689 mr1 |= MR1_CS6;
3690 break;
3691 case CS7:
3692 mr1 |= MR1_CS7;
3693 break;
3694 default:
3695 mr1 |= MR1_CS8;
3696 break;
3697 }
3698
3699 if (tiosp->c_cflag & CSTOPB)
3700 mr2 |= MR2_STOP2;
3701 else
3702 mr2 |= MR2_STOP1;
3703
3704 if (tiosp->c_cflag & PARENB) {
3705 if (tiosp->c_cflag & PARODD)
3706 mr1 |= (MR1_PARENB | MR1_PARODD);
3707 else
3708 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003709 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711
3712 mr1 |= MR1_ERRBLOCK;
3713
3714/*
3715 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3716 * space for hardware flow control and the like. This should be set to
3717 * VMIN.
3718 */
3719 mr2 |= MR2_RXFIFOHALF;
3720
3721/*
3722 * Calculate the baud rate timers. For now we will just assume that
3723 * the input and output baud are the same. The sc26198 has a fixed
3724 * baud rate table, so only discrete baud rates possible.
3725 */
3726 baudrate = tiosp->c_cflag & CBAUD;
3727 if (baudrate & CBAUDEX) {
3728 baudrate &= ~CBAUDEX;
3729 if ((baudrate < 1) || (baudrate > 4))
3730 tiosp->c_cflag &= ~CBAUDEX;
3731 else
3732 baudrate += 15;
3733 }
3734 baudrate = stl_baudrates[baudrate];
3735 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003736 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003738 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003740 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003742 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003744 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745 baudrate = (portp->baud_base / portp->custom_divisor);
3746 }
3747 if (baudrate > STL_SC26198MAXBAUD)
3748 baudrate = STL_SC26198MAXBAUD;
3749
Jiri Slabyc62429d2006-12-08 02:39:14 -08003750 if (baudrate > 0)
3751 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 if (baudrate <= sc26198_baudtable[clk])
3753 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754
3755/*
3756 * Check what form of modem signaling is required and set it up.
3757 */
3758 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003759 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 } else {
3761 iopr |= IOPR_DCDCOS;
3762 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003763 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 }
3765
3766/*
3767 * Setup sc26198 enhanced modes if we can. In particular we want to
3768 * handle as much of the flow control as possible automatically. As
3769 * well as saving a few CPU cycles it will also greatly improve flow
3770 * control reliability.
3771 */
3772 if (tiosp->c_iflag & IXON) {
3773 mr0 |= MR0_SWFTX | MR0_SWFT;
3774 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003775 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003777
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 if (tiosp->c_iflag & IXOFF)
3779 mr0 |= MR0_SWFRX;
3780
3781 if (tiosp->c_cflag & CRTSCTS) {
3782 mr2 |= MR2_AUTOCTS;
3783 mr1 |= MR1_AUTORTS;
3784 }
3785
3786/*
3787 * All sc26198 register values calculated so go through and set
3788 * them all up.
3789 */
3790
Jiri Slabya0564e12006-12-08 02:38:37 -08003791 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003793 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3794 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3795 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3797 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798
Alan Coxb65b5b52006-06-27 02:54:05 -07003799 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 BRDENABLE(portp->brdnr, portp->pagenr);
3801 stl_sc26198setreg(portp, IMR, 0);
3802 stl_sc26198updatereg(portp, MR0, mr0);
3803 stl_sc26198updatereg(portp, MR1, mr1);
3804 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3805 stl_sc26198updatereg(portp, MR2, mr2);
3806 stl_sc26198updatereg(portp, IOPIOR,
3807 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3808
3809 if (baudrate > 0) {
3810 stl_sc26198setreg(portp, TXCSR, clk);
3811 stl_sc26198setreg(portp, RXCSR, clk);
3812 }
3813
3814 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3815 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3816
3817 ipr = stl_sc26198getreg(portp, IPR);
3818 if (ipr & IPR_DCD)
3819 portp->sigs &= ~TIOCM_CD;
3820 else
3821 portp->sigs |= TIOCM_CD;
3822
3823 portp->imr = (portp->imr & ~imroff) | imron;
3824 stl_sc26198setreg(portp, IMR, portp->imr);
3825 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003826 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827}
3828
3829/*****************************************************************************/
3830
3831/*
3832 * Set the state of the DTR and RTS signals.
3833 */
3834
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003835static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836{
3837 unsigned char iopioron, iopioroff;
3838 unsigned long flags;
3839
Jiri Slabya0564e12006-12-08 02:38:37 -08003840 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3841 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
3843 iopioron = 0;
3844 iopioroff = 0;
3845 if (dtr == 0)
3846 iopioroff |= IPR_DTR;
3847 else if (dtr > 0)
3848 iopioron |= IPR_DTR;
3849 if (rts == 0)
3850 iopioroff |= IPR_RTS;
3851 else if (rts > 0)
3852 iopioron |= IPR_RTS;
3853
Alan Coxb65b5b52006-06-27 02:54:05 -07003854 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 BRDENABLE(portp->brdnr, portp->pagenr);
3856 stl_sc26198setreg(portp, IOPIOR,
3857 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3858 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003859 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860}
3861
3862/*****************************************************************************/
3863
3864/*
3865 * Return the state of the signals.
3866 */
3867
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003868static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869{
3870 unsigned char ipr;
3871 unsigned long flags;
3872 int sigs;
3873
Jiri Slabya0564e12006-12-08 02:38:37 -08003874 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
Alan Coxb65b5b52006-06-27 02:54:05 -07003876 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 BRDENABLE(portp->brdnr, portp->pagenr);
3878 ipr = stl_sc26198getreg(portp, IPR);
3879 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003880 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
3882 sigs = 0;
3883 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3884 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3885 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3886 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3887 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003888 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889}
3890
3891/*****************************************************************************/
3892
3893/*
3894 * Enable/Disable the Transmitter and/or Receiver.
3895 */
3896
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003897static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898{
3899 unsigned char ccr;
3900 unsigned long flags;
3901
Jiri Slabya0564e12006-12-08 02:38:37 -08003902 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
3904 ccr = portp->crenable;
3905 if (tx == 0)
3906 ccr &= ~CR_TXENABLE;
3907 else if (tx > 0)
3908 ccr |= CR_TXENABLE;
3909 if (rx == 0)
3910 ccr &= ~CR_RXENABLE;
3911 else if (rx > 0)
3912 ccr |= CR_RXENABLE;
3913
Alan Coxb65b5b52006-06-27 02:54:05 -07003914 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 BRDENABLE(portp->brdnr, portp->pagenr);
3916 stl_sc26198setreg(portp, SCCR, ccr);
3917 BRDDISABLE(portp->brdnr);
3918 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003919 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920}
3921
3922/*****************************************************************************/
3923
3924/*
3925 * Start/stop the Transmitter and/or Receiver.
3926 */
3927
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003928static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929{
3930 unsigned char imr;
3931 unsigned long flags;
3932
Jiri Slabya0564e12006-12-08 02:38:37 -08003933 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935 imr = portp->imr;
3936 if (tx == 0)
3937 imr &= ~IR_TXRDY;
3938 else if (tx == 1)
3939 imr |= IR_TXRDY;
3940 if (rx == 0)
3941 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3942 else if (rx > 0)
3943 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3944
Alan Coxb65b5b52006-06-27 02:54:05 -07003945 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 BRDENABLE(portp->brdnr, portp->pagenr);
3947 stl_sc26198setreg(portp, IMR, imr);
3948 BRDDISABLE(portp->brdnr);
3949 portp->imr = imr;
3950 if (tx > 0)
3951 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003952 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953}
3954
3955/*****************************************************************************/
3956
3957/*
3958 * Disable all interrupts from this port.
3959 */
3960
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003961static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962{
3963 unsigned long flags;
3964
Jiri Slabya0564e12006-12-08 02:38:37 -08003965 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Alan Coxb65b5b52006-06-27 02:54:05 -07003967 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 BRDENABLE(portp->brdnr, portp->pagenr);
3969 portp->imr = 0;
3970 stl_sc26198setreg(portp, IMR, 0);
3971 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003972 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973}
3974
3975/*****************************************************************************/
3976
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003977static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978{
3979 unsigned long flags;
3980
Jiri Slabya0564e12006-12-08 02:38:37 -08003981 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Alan Coxb65b5b52006-06-27 02:54:05 -07003983 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 BRDENABLE(portp->brdnr, portp->pagenr);
3985 if (len == 1) {
3986 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
3987 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003988 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003990
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003992 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993}
3994
3995/*****************************************************************************/
3996
3997/*
3998 * Take flow control actions...
3999 */
4000
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004001static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002{
4003 struct tty_struct *tty;
4004 unsigned long flags;
4005 unsigned char mr0;
4006
Jiri Slabya0564e12006-12-08 02:38:37 -08004007 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Jiri Slaby615e4a72006-12-08 02:38:38 -08004009 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004011 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004012 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 return;
4014
Alan Coxb65b5b52006-06-27 02:54:05 -07004015 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016 BRDENABLE(portp->brdnr, portp->pagenr);
4017
4018 if (state) {
4019 if (tty->termios->c_iflag & IXOFF) {
4020 mr0 = stl_sc26198getreg(portp, MR0);
4021 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4022 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4023 mr0 |= MR0_SWFRX;
4024 portp->stats.rxxon++;
4025 stl_sc26198wait(portp);
4026 stl_sc26198setreg(portp, MR0, mr0);
4027 }
4028/*
4029 * Question: should we return RTS to what it was before? It may
4030 * have been set by an ioctl... Suppose not, since if you have
4031 * hardware flow control set then it is pretty silly to go and
4032 * set the RTS line by hand.
4033 */
4034 if (tty->termios->c_cflag & CRTSCTS) {
4035 stl_sc26198setreg(portp, MR1,
4036 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4037 stl_sc26198setreg(portp, IOPIOR,
4038 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4039 portp->stats.rxrtson++;
4040 }
4041 } else {
4042 if (tty->termios->c_iflag & IXOFF) {
4043 mr0 = stl_sc26198getreg(portp, MR0);
4044 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4045 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4046 mr0 &= ~MR0_SWFRX;
4047 portp->stats.rxxoff++;
4048 stl_sc26198wait(portp);
4049 stl_sc26198setreg(portp, MR0, mr0);
4050 }
4051 if (tty->termios->c_cflag & CRTSCTS) {
4052 stl_sc26198setreg(portp, MR1,
4053 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4054 stl_sc26198setreg(portp, IOPIOR,
4055 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4056 portp->stats.rxrtsoff++;
4057 }
4058 }
4059
4060 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004061 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004062 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063}
4064
4065/*****************************************************************************/
4066
4067/*
4068 * Send a flow control character.
4069 */
4070
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004071static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072{
4073 struct tty_struct *tty;
4074 unsigned long flags;
4075 unsigned char mr0;
4076
Jiri Slabya0564e12006-12-08 02:38:37 -08004077 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Jiri Slaby615e4a72006-12-08 02:38:38 -08004079 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004081 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004082 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 return;
4084
Alan Coxb65b5b52006-06-27 02:54:05 -07004085 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 BRDENABLE(portp->brdnr, portp->pagenr);
4087 if (state) {
4088 mr0 = stl_sc26198getreg(portp, MR0);
4089 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4090 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4091 mr0 |= MR0_SWFRX;
4092 portp->stats.rxxon++;
4093 stl_sc26198wait(portp);
4094 stl_sc26198setreg(portp, MR0, mr0);
4095 } else {
4096 mr0 = stl_sc26198getreg(portp, MR0);
4097 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4098 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4099 mr0 &= ~MR0_SWFRX;
4100 portp->stats.rxxoff++;
4101 stl_sc26198wait(portp);
4102 stl_sc26198setreg(portp, MR0, mr0);
4103 }
4104 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004105 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004106 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107}
4108
4109/*****************************************************************************/
4110
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004111static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112{
4113 unsigned long flags;
4114
Jiri Slabya0564e12006-12-08 02:38:37 -08004115 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
Jiri Slaby615e4a72006-12-08 02:38:38 -08004117 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 return;
4119
Alan Coxb65b5b52006-06-27 02:54:05 -07004120 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 BRDENABLE(portp->brdnr, portp->pagenr);
4122 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4123 stl_sc26198setreg(portp, SCCR, portp->crenable);
4124 BRDDISABLE(portp->brdnr);
4125 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004126 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127}
4128
4129/*****************************************************************************/
4130
4131/*
4132 * Return the current state of data flow on this port. This is only
Thomas Weber6f0b31c2010-09-20 16:30:54 +02004133 * really interesting when determining if data has fully completed
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 * transmission or not... The sc26198 interrupt scheme cannot
4135 * determine when all data has actually drained, so we need to
4136 * check the port statusy register to be sure.
4137 */
4138
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004139static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140{
4141 unsigned long flags;
4142 unsigned char sr;
4143
Jiri Slabya0564e12006-12-08 02:38:37 -08004144 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Jiri Slaby615e4a72006-12-08 02:38:38 -08004146 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004147 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004149 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150
Alan Coxb65b5b52006-06-27 02:54:05 -07004151 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 BRDENABLE(portp->brdnr, portp->pagenr);
4153 sr = stl_sc26198getreg(portp, SR);
4154 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004155 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156
Jesper Juhl014c2542006-01-15 02:37:08 +01004157 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158}
4159
4160/*****************************************************************************/
4161
4162/*
4163 * Delay for a small amount of time, to give the sc26198 a chance
4164 * to process a command...
4165 */
4166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004167static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168{
4169 int i;
4170
Jiri Slabya0564e12006-12-08 02:38:37 -08004171 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Jiri Slaby615e4a72006-12-08 02:38:38 -08004173 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 return;
4175
Jiri Slabyc62429d2006-12-08 02:39:14 -08004176 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 stl_sc26198getglobreg(portp, TSTR);
4178}
4179
4180/*****************************************************************************/
4181
4182/*
4183 * If we are TX flow controlled and in IXANY mode then we may
4184 * need to unflow control here. We gotta do this because of the
4185 * automatic flow control modes of the sc26198.
4186 */
4187
Jiri Slaby60be4812006-12-08 02:38:40 -08004188static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189{
4190 unsigned char mr0;
4191
4192 mr0 = stl_sc26198getreg(portp, MR0);
4193 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4194 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4195 stl_sc26198wait(portp);
4196 stl_sc26198setreg(portp, MR0, mr0);
4197 clear_bit(ASYI_TXFLOWED, &portp->istate);
4198}
4199
4200/*****************************************************************************/
4201
4202/*
4203 * Interrupt service routine for sc26198 panels.
4204 */
4205
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004206static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004208 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 unsigned int iack;
4210
Alan Coxb65b5b52006-06-27 02:54:05 -07004211 spin_lock(&brd_lock);
4212
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213/*
4214 * Work around bug in sc26198 chip... Cannot have A6 address
4215 * line of UART high, else iack will be returned as 0.
4216 */
4217 outb(0, (iobase + 1));
4218
4219 iack = inb(iobase + XP_IACK);
4220 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4221
4222 if (iack & IVR_RXDATA)
4223 stl_sc26198rxisr(portp, iack);
4224 else if (iack & IVR_TXDATA)
4225 stl_sc26198txisr(portp);
4226 else
4227 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004228
4229 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230}
4231
4232/*****************************************************************************/
4233
4234/*
4235 * Transmit interrupt handler. This has gotta be fast! Handling TX
4236 * chars is pretty simple, stuff as many as possible from the TX buffer
4237 * into the sc26198 FIFO.
4238 * In practice it is possible that interrupts are enabled but that the
4239 * port has been hung up. Need to handle not having any TX buffer here,
4240 * this is done by using the side effect that head and tail will also
4241 * be NULL if the buffer has been freed.
4242 */
4243
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004244static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245{
Alan Coxd18a7502008-10-13 10:40:07 +01004246 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 unsigned int ioaddr;
4248 unsigned char mr0;
4249 int len, stlen;
4250 char *head, *tail;
4251
Jiri Slabya0564e12006-12-08 02:38:37 -08004252 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
4254 ioaddr = portp->ioaddr;
4255 head = portp->tx.head;
4256 tail = portp->tx.tail;
4257 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4258 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4259 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4260 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004261 tty = tty_port_tty_get(&portp->port);
4262 if (tty) {
4263 tty_wakeup(tty);
4264 tty_kref_put(tty);
4265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 }
4267
4268 if (len == 0) {
4269 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4270 mr0 = inb(ioaddr + XP_DATA);
4271 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4272 portp->imr &= ~IR_TXRDY;
4273 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4274 outb(portp->imr, (ioaddr + XP_DATA));
4275 clear_bit(ASYI_TXBUSY, &portp->istate);
4276 } else {
4277 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4278 outb(mr0, (ioaddr + XP_DATA));
4279 }
4280 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004281 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004283 stlen = min_t(unsigned int, len,
4284 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 outb(GTXFIFO, (ioaddr + XP_ADDR));
4286 outsb((ioaddr + XP_DATA), tail, stlen);
4287 len -= stlen;
4288 tail += stlen;
4289 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4290 tail = portp->tx.buf;
4291 if (len > 0) {
4292 outsb((ioaddr + XP_DATA), tail, len);
4293 tail += len;
4294 }
4295 portp->tx.tail = tail;
4296 }
4297}
4298
4299/*****************************************************************************/
4300
4301/*
4302 * Receive character interrupt handler. Determine if we have good chars
4303 * or bad chars and then process appropriately. Good chars are easy
4304 * just shove the lot into the RX buffer and set all status byte to 0.
4305 * If a bad RX char then process as required. This routine needs to be
4306 * fast! In practice it is possible that we get an interrupt on a port
4307 * that is closed. This can happen on hangups - since they completely
4308 * shutdown a port not in user context. Need to handle this case.
4309 */
4310
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004311static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312{
4313 struct tty_struct *tty;
4314 unsigned int len, buflen, ioaddr;
4315
Jiri Slabya0564e12006-12-08 02:38:37 -08004316 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
Alan Coxd18a7502008-10-13 10:40:07 +01004318 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 ioaddr = portp->ioaddr;
4320 outb(GIBCR, (ioaddr + XP_ADDR));
4321 len = inb(ioaddr + XP_DATA) + 1;
4322
4323 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004324 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004325 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 outb(GRXFIFO, (ioaddr + XP_ADDR));
4327 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4328 portp->stats.rxlost += len;
4329 portp->stats.rxtotal += len;
4330 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004331 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004333 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004335 tty_prepare_flip_string(tty, &ptr, len);
4336 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 tty_schedule_flip(tty);
4338 portp->stats.rxtotal += len;
4339 }
4340 }
4341 } else {
4342 stl_sc26198rxbadchars(portp);
4343 }
4344
4345/*
4346 * If we are TX flow controlled and in IXANY mode then we may need
4347 * to unflow control here. We gotta do this because of the automatic
4348 * flow control modes of the sc26198.
4349 */
4350 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004351 if ((tty != NULL) &&
4352 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 (tty->termios->c_iflag & IXANY)) {
4354 stl_sc26198txunflow(portp, tty);
4355 }
4356 }
Alan Coxd18a7502008-10-13 10:40:07 +01004357 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358}
4359
4360/*****************************************************************************/
4361
4362/*
4363 * Process an RX bad character.
4364 */
4365
Jiri Slaby60be4812006-12-08 02:38:40 -08004366static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367{
4368 struct tty_struct *tty;
4369 unsigned int ioaddr;
4370
Alan Coxd18a7502008-10-13 10:40:07 +01004371 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 ioaddr = portp->ioaddr;
4373
4374 if (status & SR_RXPARITY)
4375 portp->stats.rxparity++;
4376 if (status & SR_RXFRAMING)
4377 portp->stats.rxframing++;
4378 if (status & SR_RXOVERRUN)
4379 portp->stats.rxoverrun++;
4380 if (status & SR_RXBREAK)
4381 portp->stats.rxbreaks++;
4382
Jiri Slaby615e4a72006-12-08 02:38:38 -08004383 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 ((portp->rxignoremsk & status) == 0)) {
4385 if (portp->rxmarkmsk & status) {
4386 if (status & SR_RXBREAK) {
4387 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004388 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004389 do_SAK(tty);
4390 BRDENABLE(portp->brdnr, portp->pagenr);
4391 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004392 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004394 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004396 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004398 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004400 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
Alan Cox33f0f882006-01-09 20:54:13 -08004403 tty_insert_flip_char(tty, ch, status);
4404 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
4406 if (status == 0)
4407 portp->stats.rxtotal++;
4408 }
Alan Coxd18a7502008-10-13 10:40:07 +01004409 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410}
4411
4412/*****************************************************************************/
4413
4414/*
4415 * Process all characters in the RX FIFO of the UART. Check all char
4416 * status bytes as well, and process as required. We need to check
4417 * all bytes in the FIFO, in case some more enter the FIFO while we
4418 * are here. To get the exact character error type we need to switch
4419 * into CHAR error mode (that is why we need to make sure we empty
4420 * the FIFO).
4421 */
4422
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004423static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
4425 unsigned char status, mr1;
4426 char ch;
4427
4428/*
4429 * To get the precise error type for each character we must switch
4430 * back into CHAR error mode.
4431 */
4432 mr1 = stl_sc26198getreg(portp, MR1);
4433 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4434
4435 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4436 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4437 ch = stl_sc26198getreg(portp, RXFIFO);
4438 stl_sc26198rxbadch(portp, status, ch);
4439 }
4440
4441/*
4442 * To get correct interrupt class we must switch back into BLOCK
4443 * error mode.
4444 */
4445 stl_sc26198setreg(portp, MR1, mr1);
4446}
4447
4448/*****************************************************************************/
4449
4450/*
4451 * Other interrupt handler. This includes modem signals, flow
4452 * control actions, etc. Most stuff is left to off-level interrupt
4453 * processing time.
4454 */
4455
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004456static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457{
4458 unsigned char cir, ipr, xisr;
4459
Jiri Slabya0564e12006-12-08 02:38:37 -08004460 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
4462 cir = stl_sc26198getglobreg(portp, CIR);
4463
4464 switch (cir & CIR_SUBTYPEMASK) {
4465 case CIR_SUBCOS:
4466 ipr = stl_sc26198getreg(portp, IPR);
4467 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004468 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 portp->stats.modem++;
4470 }
4471 break;
4472 case CIR_SUBXONXOFF:
4473 xisr = stl_sc26198getreg(portp, XISR);
4474 if (xisr & XISR_RXXONGOT) {
4475 set_bit(ASYI_TXFLOWED, &portp->istate);
4476 portp->stats.txxoff++;
4477 }
4478 if (xisr & XISR_RXXOFFGOT) {
4479 clear_bit(ASYI_TXFLOWED, &portp->istate);
4480 portp->stats.txxon++;
4481 }
4482 break;
4483 case CIR_SUBBREAK:
4484 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4485 stl_sc26198rxbadchars(portp);
4486 break;
4487 default:
4488 break;
4489 }
4490}
4491
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004492static void stl_free_isabrds(void)
4493{
4494 struct stlbrd *brdp;
4495 unsigned int i;
4496
4497 for (i = 0; i < stl_nrbrds; i++) {
4498 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4499 continue;
4500
4501 free_irq(brdp->irq, brdp);
4502
4503 stl_cleanup_panels(brdp);
4504
4505 release_region(brdp->ioaddr1, brdp->iosize1);
4506 if (brdp->iosize2 > 0)
4507 release_region(brdp->ioaddr2, brdp->iosize2);
4508
4509 kfree(brdp);
4510 stl_brds[i] = NULL;
4511 }
4512}
4513
Jiri Slaby23b85a12006-12-08 02:38:40 -08004514/*
4515 * Loadable module initialization stuff.
4516 */
4517static int __init stallion_module_init(void)
4518{
Jiri Slaby843b5682006-12-08 02:39:12 -08004519 struct stlbrd *brdp;
4520 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004521 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004522 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004523
4524 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4525
4526 spin_lock_init(&stallion_lock);
4527 spin_lock_init(&brd_lock);
4528
Jiri Slabye4151092007-06-08 13:46:52 -07004529 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4530 if (!stl_serial) {
4531 retval = -ENOMEM;
4532 goto err;
4533 }
4534
4535 stl_serial->owner = THIS_MODULE;
4536 stl_serial->driver_name = stl_drvname;
4537 stl_serial->name = "ttyE";
4538 stl_serial->major = STL_SERIALMAJOR;
4539 stl_serial->minor_start = 0;
4540 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4541 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4542 stl_serial->init_termios = stl_deftermios;
4543 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4544 tty_set_operations(stl_serial, &stl_ops);
4545
4546 retval = tty_register_driver(stl_serial);
4547 if (retval) {
4548 printk("STALLION: failed to register serial driver\n");
4549 goto err_frtty;
4550 }
4551
Jiri Slaby843b5682006-12-08 02:39:12 -08004552/*
4553 * Find any dynamically supported boards. That is via module load
4554 * line options.
4555 */
4556 for (i = stl_nrbrds; i < stl_nargs; i++) {
4557 memset(&conf, 0, sizeof(conf));
4558 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4559 continue;
4560 if ((brdp = stl_allocbrd()) == NULL)
4561 continue;
4562 brdp->brdnr = i;
4563 brdp->brdtype = conf.brdtype;
4564 brdp->ioaddr1 = conf.ioaddr1;
4565 brdp->ioaddr2 = conf.ioaddr2;
4566 brdp->irq = conf.irq;
4567 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004568 stl_brds[brdp->brdnr] = brdp;
4569 if (stl_brdinit(brdp)) {
4570 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004571 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004572 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004573 for (j = 0; j < brdp->nrports; j++)
4574 tty_register_device(stl_serial,
4575 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004576 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004577 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004578 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004579
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004580 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004581 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004582 if (retval && stl_nrbrds == 0) {
4583 printk(KERN_ERR "STALLION: can't register pci driver\n");
4584 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004585 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004586
4587/*
4588 * Set up a character driver for per board stuff. This is mainly used
4589 * to do stats ioctls on the ports.
4590 */
4591 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4592 printk("STALLION: failed to register serial board device\n");
4593
4594 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004595 if (IS_ERR(stallion_class))
4596 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004597 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004598 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4599 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004600
Jiri Slaby23b85a12006-12-08 02:38:40 -08004601 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004602err_unrtty:
4603 tty_unregister_driver(stl_serial);
4604err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004605 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004606err:
4607 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004608}
4609
4610static void __exit stallion_module_exit(void)
4611{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004612 struct stlbrd *brdp;
4613 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004614
4615 pr_debug("cleanup_module()\n");
4616
4617 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4618 stl_drvversion);
4619
4620/*
4621 * Free up all allocated resources used by the ports. This includes
4622 * memory and interrupts. As part of this process we will also do
4623 * a hangup on every open port - to try to flush out any processes
4624 * hanging onto ports.
4625 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004626 for (i = 0; i < stl_nrbrds; i++) {
4627 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4628 continue;
4629 for (j = 0; j < brdp->nrports; j++)
4630 tty_unregister_device(stl_serial,
4631 brdp->brdnr * STL_MAXPORTS + j);
4632 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004633
Jiri Slaby23b85a12006-12-08 02:38:40 -08004634 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004635 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004636 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004637 class_destroy(stallion_class);
4638
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004639 pci_unregister_driver(&stl_pcidriver);
4640
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004641 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004642
4643 tty_unregister_driver(stl_serial);
4644 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004645}
4646
4647module_init(stallion_module_init);
4648module_exit(stallion_module_exit);
4649
4650MODULE_AUTHOR("Greg Ungerer");
4651MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4652MODULE_LICENSE("GPL");