blob: 19db1eb87c26fa22eb9e4f17d8b6ec384e6c021b [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>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080066 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Define global place to put buffer overflow characters.
125 */
126static char stl_unwanted[SC26198_RXFIFOSIZE];
127
128/*****************************************************************************/
129
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800130static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800131static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/*
134 * Per board state flags. Used with the state field of the board struct.
135 * Not really much here!
136 */
137#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800138#define STL_PROBED 0x2
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/*
142 * Define the port structure istate flags. These set of flags are
143 * modified at interrupt time - so setting and reseting them needs
144 * to be atomic. Use the bit clear/setting routines for this.
145 */
146#define ASYI_TXBUSY 1
147#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800148#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/*
151 * Define an array of board names as printable strings. Handy for
152 * referencing boards when printing trace and stuff.
153 */
154static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800155 NULL,
156 NULL,
157 NULL,
158 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,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 "EasyIO",
176 "EC8/32-AT",
177 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800178 NULL,
179 NULL,
180 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 "EC8/32-PCI",
182 "EC8/64-PCI",
183 "EasyIO-PCI",
184};
185
186/*****************************************************************************/
187
188/*
189 * Define some string labels for arguments passed from the module
190 * load line. These allow for easy board definitions, and easy
191 * modification of the io, memory and irq resoucres.
192 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800193static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static char *board0[4];
195static char *board1[4];
196static char *board2[4];
197static char *board3[4];
198
199static char **stl_brdsp[] = {
200 (char **) &board0,
201 (char **) &board1,
202 (char **) &board2,
203 (char **) &board3
204};
205
206/*
207 * Define a set of common board names, and types. This is used to
208 * parse any module arguments.
209 */
210
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800211static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 char *name;
213 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800214} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 { "easyio", BRD_EASYIO },
216 { "eio", BRD_EASYIO },
217 { "20", BRD_EASYIO },
218 { "ec8/32", BRD_ECH },
219 { "ec8/32-at", BRD_ECH },
220 { "ec8/32-isa", BRD_ECH },
221 { "ech", BRD_ECH },
222 { "echat", BRD_ECH },
223 { "21", BRD_ECH },
224 { "ec8/32-mc", BRD_ECHMC },
225 { "ec8/32-mca", BRD_ECHMC },
226 { "echmc", BRD_ECHMC },
227 { "echmca", BRD_ECHMC },
228 { "22", BRD_ECHMC },
229 { "ec8/32-pc", BRD_ECHPCI },
230 { "ec8/32-pci", BRD_ECHPCI },
231 { "26", BRD_ECHPCI },
232 { "ec8/64-pc", BRD_ECH64PCI },
233 { "ec8/64-pci", BRD_ECH64PCI },
234 { "ech-pci", BRD_ECH64PCI },
235 { "echpci", BRD_ECH64PCI },
236 { "echpc", BRD_ECH64PCI },
237 { "27", BRD_ECH64PCI },
238 { "easyio-pc", BRD_EASYIOPCI },
239 { "easyio-pci", BRD_EASYIOPCI },
240 { "eio-pci", BRD_EASYIOPCI },
241 { "eiopci", BRD_EASYIOPCI },
242 { "28", BRD_EASYIOPCI },
243};
244
245/*
246 * Define the module agruments.
247 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249module_param_array(board0, charp, &stl_nargs, 0);
250MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
251module_param_array(board1, charp, &stl_nargs, 0);
252MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
253module_param_array(board2, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board3, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
257
258/*****************************************************************************/
259
260/*
261 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
262 * to the directly accessible io ports of these boards (not the uarts -
263 * they are in cd1400.h and sc26198.h).
264 */
265#define EIO_8PORTRS 0x04
266#define EIO_4PORTRS 0x05
267#define EIO_8PORTDI 0x00
268#define EIO_8PORTM 0x06
269#define EIO_MK3 0x03
270#define EIO_IDBITMASK 0x07
271
272#define EIO_BRDMASK 0xf0
273#define ID_BRD4 0x10
274#define ID_BRD8 0x20
275#define ID_BRD16 0x30
276
277#define EIO_INTRPEND 0x08
278#define EIO_INTEDGE 0x00
279#define EIO_INTLEVEL 0x08
280#define EIO_0WS 0x10
281
282#define ECH_ID 0xa0
283#define ECH_IDBITMASK 0xe0
284#define ECH_BRDENABLE 0x08
285#define ECH_BRDDISABLE 0x00
286#define ECH_INTENABLE 0x01
287#define ECH_INTDISABLE 0x00
288#define ECH_INTLEVEL 0x02
289#define ECH_INTEDGE 0x00
290#define ECH_INTRPEND 0x01
291#define ECH_BRDRESET 0x01
292
293#define ECHMC_INTENABLE 0x01
294#define ECHMC_BRDRESET 0x02
295
296#define ECH_PNLSTATUS 2
297#define ECH_PNL16PORT 0x20
298#define ECH_PNLIDMASK 0x07
299#define ECH_PNLXPID 0x40
300#define ECH_PNLINTRPEND 0x80
301
302#define ECH_ADDR2MASK 0x1e0
303
304/*
305 * Define the vector mapping bits for the programmable interrupt board
306 * hardware. These bits encode the interrupt for the board to use - it
307 * is software selectable (except the EIO-8M).
308 */
309static unsigned char stl_vecmap[] = {
310 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
311 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
312};
313
314/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700315 * Lock ordering is that you may not take stallion_lock holding
316 * brd_lock.
317 */
318
319static spinlock_t brd_lock; /* Guard the board mapping */
320static spinlock_t stallion_lock; /* Guard the tty driver */
321
322/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 * Set up enable and disable macros for the ECH boards. They require
324 * the secondary io address space to be activated and deactivated.
325 * This way all ECH boards can share their secondary io region.
326 * If this is an ECH-PCI board then also need to set the page pointer
327 * to point to the correct page.
328 */
329#define BRDENABLE(brdnr,pagenr) \
330 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
331 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
332 stl_brds[(brdnr)]->ioctrl); \
333 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
334 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
335
336#define BRDDISABLE(brdnr) \
337 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
338 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
339 stl_brds[(brdnr)]->ioctrl);
340
341#define STL_CD1400MAXBAUD 230400
342#define STL_SC26198MAXBAUD 460800
343
344#define STL_BAUDBASE 115200
345#define STL_CLOSEDELAY (5 * HZ / 10)
346
347/*****************************************************************************/
348
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349/*
350 * Define the Stallion PCI vendor and device IDs.
351 */
352#ifndef PCI_VENDOR_ID_STALLION
353#define PCI_VENDOR_ID_STALLION 0x124d
354#endif
355#ifndef PCI_DEVICE_ID_ECHPCI832
356#define PCI_DEVICE_ID_ECHPCI832 0x0000
357#endif
358#ifndef PCI_DEVICE_ID_ECHPCI864
359#define PCI_DEVICE_ID_ECHPCI864 0x0002
360#endif
361#ifndef PCI_DEVICE_ID_EIOPCI
362#define PCI_DEVICE_ID_EIOPCI 0x0003
363#endif
364
365/*
366 * Define structure to hold all Stallion PCI boards.
367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800369static struct pci_device_id stl_pcibrds[] = {
370 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
371 .driver_data = BRD_ECH64PCI },
372 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
373 .driver_data = BRD_EASYIOPCI },
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
375 .driver_data = BRD_ECHPCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
377 .driver_data = BRD_ECHPCI },
378 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800380MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382/*****************************************************************************/
383
384/*
385 * Define macros to extract a brd/port number from a minor number.
386 */
387#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
388#define MINOR2PORT(min) ((min) & 0x3f)
389
390/*
391 * Define a baud rate table that converts termios baud rate selector
392 * into the actual baud rate value. All baud rate calculations are
393 * based on the actual baud rate required.
394 */
395static unsigned int stl_baudrates[] = {
396 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
397 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
398};
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400/*****************************************************************************/
401
402/*
403 * Declare all those functions in this driver!
404 */
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800407static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800408static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
409static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800410static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412/*
413 * CD1400 uart specific handling functions.
414 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800415static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
416static int stl_cd1400getreg(struct stlport *portp, int regnr);
417static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
419static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800420static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800421static int stl_cd1400getsignals(struct stlport *portp);
422static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
423static void stl_cd1400ccrwait(struct stlport *portp);
424static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
425static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
426static void stl_cd1400disableintrs(struct stlport *portp);
427static void stl_cd1400sendbreak(struct stlport *portp, int len);
428static void stl_cd1400flowctrl(struct stlport *portp, int state);
429static void stl_cd1400sendflow(struct stlport *portp, int state);
430static void stl_cd1400flush(struct stlport *portp);
431static int stl_cd1400datastate(struct stlport *portp);
432static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
433static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
434static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
435static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
436static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800438static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440/*
441 * SC26198 uart specific handling functions.
442 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800443static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
444static int stl_sc26198getreg(struct stlport *portp, int regnr);
445static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
447static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
448static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800449static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800450static int stl_sc26198getsignals(struct stlport *portp);
451static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
452static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
453static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
454static void stl_sc26198disableintrs(struct stlport *portp);
455static void stl_sc26198sendbreak(struct stlport *portp, int len);
456static void stl_sc26198flowctrl(struct stlport *portp, int state);
457static void stl_sc26198sendflow(struct stlport *portp, int state);
458static void stl_sc26198flush(struct stlport *portp);
459static int stl_sc26198datastate(struct stlport *portp);
460static void stl_sc26198wait(struct stlport *portp);
461static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
462static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
463static void stl_sc26198txisr(struct stlport *port);
464static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
465static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
466static void stl_sc26198rxbadchars(struct stlport *portp);
467static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469/*****************************************************************************/
470
471/*
472 * Generic UART support structure.
473 */
474typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800475 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
476 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800477 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800478 int (*getsignals)(struct stlport *portp);
479 void (*setsignals)(struct stlport *portp, int dtr, int rts);
480 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
481 void (*startrxtx)(struct stlport *portp, int rx, int tx);
482 void (*disableintrs)(struct stlport *portp);
483 void (*sendbreak)(struct stlport *portp, int len);
484 void (*flowctrl)(struct stlport *portp, int state);
485 void (*sendflow)(struct stlport *portp, int state);
486 void (*flush)(struct stlport *portp);
487 int (*datastate)(struct stlport *portp);
488 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489} uart_t;
490
491/*
492 * Define some macros to make calling these functions nice and clean.
493 */
494#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
495#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
496#define stl_setport (* ((uart_t *) portp->uartp)->setport)
497#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
498#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
499#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
500#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
501#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
502#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
503#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
504#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
505#define stl_flush (* ((uart_t *) portp->uartp)->flush)
506#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
507
508/*****************************************************************************/
509
510/*
511 * CD1400 UART specific data initialization.
512 */
513static uart_t stl_cd1400uart = {
514 stl_cd1400panelinit,
515 stl_cd1400portinit,
516 stl_cd1400setport,
517 stl_cd1400getsignals,
518 stl_cd1400setsignals,
519 stl_cd1400enablerxtx,
520 stl_cd1400startrxtx,
521 stl_cd1400disableintrs,
522 stl_cd1400sendbreak,
523 stl_cd1400flowctrl,
524 stl_cd1400sendflow,
525 stl_cd1400flush,
526 stl_cd1400datastate,
527 stl_cd1400eiointr
528};
529
530/*
531 * Define the offsets within the register bank of a cd1400 based panel.
532 * These io address offsets are common to the EasyIO board as well.
533 */
534#define EREG_ADDR 0
535#define EREG_DATA 4
536#define EREG_RXACK 5
537#define EREG_TXACK 6
538#define EREG_MDACK 7
539
540#define EREG_BANKSIZE 8
541
542#define CD1400_CLK 25000000
543#define CD1400_CLK8M 20000000
544
545/*
546 * Define the cd1400 baud rate clocks. These are used when calculating
547 * what clock and divisor to use for the required baud rate. Also
548 * define the maximum baud rate allowed, and the default base baud.
549 */
550static int stl_cd1400clkdivs[] = {
551 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
552};
553
554/*****************************************************************************/
555
556/*
557 * SC26198 UART specific data initization.
558 */
559static uart_t stl_sc26198uart = {
560 stl_sc26198panelinit,
561 stl_sc26198portinit,
562 stl_sc26198setport,
563 stl_sc26198getsignals,
564 stl_sc26198setsignals,
565 stl_sc26198enablerxtx,
566 stl_sc26198startrxtx,
567 stl_sc26198disableintrs,
568 stl_sc26198sendbreak,
569 stl_sc26198flowctrl,
570 stl_sc26198sendflow,
571 stl_sc26198flush,
572 stl_sc26198datastate,
573 stl_sc26198intr
574};
575
576/*
577 * Define the offsets within the register bank of a sc26198 based panel.
578 */
579#define XP_DATA 0
580#define XP_ADDR 1
581#define XP_MODID 2
582#define XP_STATUS 2
583#define XP_IACK 3
584
585#define XP_BANKSIZE 4
586
587/*
588 * Define the sc26198 baud rate table. Offsets within the table
589 * represent the actual baud rate selector of sc26198 registers.
590 */
591static unsigned int sc26198_baudtable[] = {
592 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
593 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
594 230400, 460800, 921600
595};
596
Tobias Klauserfe971072006-01-09 20:54:02 -0800597#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599/*****************************************************************************/
600
601/*
602 * Define the driver info for a user level control device. Used mainly
603 * to get at port stats - only not using the port device itself.
604 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700605static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 .owner = THIS_MODULE,
607 .ioctl = stl_memioctl,
608};
609
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800610static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800612static void stl_cd_change(struct stlport *portp)
613{
614 unsigned int oldsigs = portp->sigs;
615
Alan Coxf8ae4762008-07-16 21:56:37 +0100616 if (!portp->port.tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800617 return;
618
619 portp->sigs = stl_getsignals(portp);
620
621 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100622 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800623
624 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100625 if (portp->port.flags & ASYNC_CHECK_CD)
626 tty_hangup(portp->port.tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800627}
628
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 * Check for any arguments passed in on the module load command line.
631 */
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633/*****************************************************************************/
634
635/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 * Parse the supplied argument string, into the board conf struct.
637 */
638
Jiri Slaby40e82652006-12-08 02:38:41 -0800639static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
641 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800642 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Jiri Slabya0564e12006-12-08 02:38:37 -0800644 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Jiri Slaby615e4a72006-12-08 02:38:38 -0800646 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slabyc62429d2006-12-08 02:39:14 -0800649 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800650 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Jiri Slabyc62429d2006-12-08 02:39:14 -0800652 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
654 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800655
Tobias Klauserfe971072006-01-09 20:54:02 -0800656 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800658 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660
661 confp->brdtype = stl_brdstr[i].type;
662
663 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800664 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800665 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 i++;
667 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800668 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800669 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 i++;
671 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800672 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800673 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100674 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
677/*****************************************************************************/
678
679/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 * Allocate a new board structure. Fill out the basic info in it.
681 */
682
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800683static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800685 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800687 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800688 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700689 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800691 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 }
693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100695 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696}
697
698/*****************************************************************************/
699
700static int stl_open(struct tty_struct *tty, struct file *filp)
701{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800702 struct stlport *portp;
703 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800704 unsigned int minordev, brdnr, panelnr;
705 int portnr, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Jiri Slabya0564e12006-12-08 02:38:37 -0800707 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 minordev = tty->index;
710 brdnr = MINOR2BRD(minordev);
711 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100712 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800714 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100715 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800717 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800718 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 break;
720 if (minordev < brdp->panels[panelnr]->nrports) {
721 portnr = minordev;
722 break;
723 }
724 minordev -= brdp->panels[panelnr]->nrports;
725 }
726 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100727 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
729 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800730 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100731 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733/*
734 * On the first open of the device setup the port hardware, and
735 * initialize the per port data structure.
736 */
Alan Coxf8ae4762008-07-16 21:56:37 +0100737 portp->port.tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 tty->driver_data = portp;
Alan Coxf8ae4762008-07-16 21:56:37 +0100739 portp->port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Alan Coxf8ae4762008-07-16 21:56:37 +0100741 if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800742 if (!portp->tx.buf) {
743 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
744 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100745 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 portp->tx.head = portp->tx.buf;
747 portp->tx.tail = portp->tx.buf;
748 }
749 stl_setport(portp, tty->termios);
750 portp->sigs = stl_getsignals(portp);
751 stl_setsignals(portp, 1, 1);
752 stl_enablerxtx(portp, 1, 1);
753 stl_startrxtx(portp, 1, 0);
754 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100755 portp->port.flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 }
757
758/*
759 * Check if this port is in the middle of closing. If so then wait
760 * until it is closed then return error status, based on flag settings.
761 * The sleep here does not need interrupt protection since the wakeup
762 * for it is done with the same context.
763 */
Alan Coxf8ae4762008-07-16 21:56:37 +0100764 if (portp->port.flags & ASYNC_CLOSING) {
765 interruptible_sleep_on(&portp->port.close_wait);
766 if (portp->port.flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100767 return -EAGAIN;
768 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
770
771/*
772 * Based on type of open being done check if it can overlap with any
773 * previous opens still in effect. If we are a normal serial device
774 * then also we might have to wait for carrier.
775 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800776 if (!(filp->f_flags & O_NONBLOCK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100778 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800779
Alan Coxf8ae4762008-07-16 21:56:37 +0100780 portp->port.flags |= ASYNC_NORMAL_ACTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Jesper Juhl014c2542006-01-15 02:37:08 +0100782 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783}
784
785/*****************************************************************************/
786
787/*
788 * Possibly need to wait for carrier (DCD signal) to come high. Say
789 * maybe because if we are clocal then we don't need to wait...
790 */
791
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800792static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
794 unsigned long flags;
795 int rc, doclocal;
796
Jiri Slabya0564e12006-12-08 02:38:37 -0800797 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
799 rc = 0;
800 doclocal = 0;
801
Alan Coxb65b5b52006-06-27 02:54:05 -0700802 spin_lock_irqsave(&stallion_lock, flags);
803
Alan Coxf8ae4762008-07-16 21:56:37 +0100804 if (portp->port.tty->termios->c_cflag & CLOCAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 doclocal++;
806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 portp->openwaitcnt++;
808 if (! tty_hung_up_p(filp))
Alan Coxf8ae4762008-07-16 21:56:37 +0100809 portp->port.count--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700812 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 stl_setsignals(portp, 1, 1);
814 if (tty_hung_up_p(filp) ||
Alan Coxf8ae4762008-07-16 21:56:37 +0100815 ((portp->port.flags & ASYNC_INITIALIZED) == 0)) {
816 if (portp->port.flags & ASYNC_HUP_NOTIFY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 rc = -EBUSY;
818 else
819 rc = -ERESTARTSYS;
820 break;
821 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100822 if (((portp->port.flags & ASYNC_CLOSING) == 0) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -0800823 (doclocal || (portp->sigs & TIOCM_CD)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 if (signal_pending(current)) {
826 rc = -ERESTARTSYS;
827 break;
828 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700829 /* FIXME */
Alan Coxf8ae4762008-07-16 21:56:37 +0100830 interruptible_sleep_on(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832
833 if (! tty_hung_up_p(filp))
Alan Coxf8ae4762008-07-16 21:56:37 +0100834 portp->port.count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700836 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Jesper Juhl014c2542006-01-15 02:37:08 +0100838 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839}
840
841/*****************************************************************************/
842
Jiri Slaby96b066b2006-12-08 02:38:42 -0800843static void stl_flushbuffer(struct tty_struct *tty)
844{
845 struct stlport *portp;
846
847 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
848
849 if (tty == NULL)
850 return;
851 portp = tty->driver_data;
852 if (portp == NULL)
853 return;
854
855 stl_flush(portp);
856 tty_wakeup(tty);
857}
858
859/*****************************************************************************/
860
861static void stl_waituntilsent(struct tty_struct *tty, int timeout)
862{
863 struct stlport *portp;
864 unsigned long tend;
865
866 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
867
868 if (tty == NULL)
869 return;
870 portp = tty->driver_data;
871 if (portp == NULL)
872 return;
873
874 if (timeout == 0)
875 timeout = HZ;
876 tend = jiffies + timeout;
877
Alan Cox978e5952008-04-30 00:53:59 -0700878 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800879 while (stl_datastate(portp)) {
880 if (signal_pending(current))
881 break;
882 msleep_interruptible(20);
883 if (time_after_eq(jiffies, tend))
884 break;
885 }
Alan Cox978e5952008-04-30 00:53:59 -0700886 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800887}
888
889/*****************************************************************************/
890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891static void stl_close(struct tty_struct *tty, struct file *filp)
892{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800893 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 unsigned long flags;
895
Jiri Slabya0564e12006-12-08 02:38:37 -0800896 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897
898 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800899 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 return;
901
Alan Coxb65b5b52006-06-27 02:54:05 -0700902 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700904 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 return;
906 }
Alan Coxf8ae4762008-07-16 21:56:37 +0100907 if ((tty->count == 1) && (portp->port.count != 1))
908 portp->port.count = 1;
909 if (portp->port.count-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700910 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 return;
912 }
913
Alan Coxf8ae4762008-07-16 21:56:37 +0100914 portp->port.count = 0;
915 portp->port.flags |= ASYNC_CLOSING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
917/*
918 * May want to wait for any data to drain before closing. The BUSY
919 * flag keeps track of whether we are still sending or not - it is
920 * very accurate for the cd1400, not quite so for the sc26198.
921 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
922 */
923 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700924
925 spin_unlock_irqrestore(&stallion_lock, flags);
926
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
928 tty_wait_until_sent(tty, portp->closing_wait);
929 stl_waituntilsent(tty, (HZ / 2));
930
Alan Coxb65b5b52006-06-27 02:54:05 -0700931
932 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100933 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700934 spin_unlock_irqrestore(&stallion_lock, flags);
935
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 stl_disableintrs(portp);
937 if (tty->termios->c_cflag & HUPCL)
938 stl_setsignals(portp, 0, 0);
939 stl_enablerxtx(portp, 0, 0);
940 stl_flushbuffer(tty);
941 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800942 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800944 portp->tx.buf = NULL;
945 portp->tx.head = NULL;
946 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 }
948 set_bit(TTY_IO_ERROR, &tty->flags);
949 tty_ldisc_flush(tty);
950
951 tty->closing = 0;
Alan Coxf8ae4762008-07-16 21:56:37 +0100952 portp->port.tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954 if (portp->openwaitcnt) {
955 if (portp->close_delay)
956 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
Alan Coxf8ae4762008-07-16 21:56:37 +0100957 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
959
Alan Coxf8ae4762008-07-16 21:56:37 +0100960 portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
961 wake_up_interruptible(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962}
963
964/*****************************************************************************/
965
966/*
967 * Write routine. Take data and stuff it in to the TX ring queue.
968 * If transmit interrupts are not running then start them.
969 */
970
971static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
972{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800973 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 unsigned int len, stlen;
975 unsigned char *chbuf;
976 char *head, *tail;
977
Jiri Slabya0564e12006-12-08 02:38:37 -0800978 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800981 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100982 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800983 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100984 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986/*
987 * If copying direct from user space we must cater for page faults,
988 * causing us to "sleep" here for a while. To handle this copy in all
989 * the data we need now, into a local buffer. Then when we got it all
990 * copy it into the TX buffer.
991 */
992 chbuf = (unsigned char *) buf;
993
994 head = portp->tx.head;
995 tail = portp->tx.tail;
996 if (head >= tail) {
997 len = STL_TXBUFSIZE - (head - tail) - 1;
998 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
999 } else {
1000 len = tail - head - 1;
1001 stlen = len;
1002 }
1003
Jiri Slaby843b5682006-12-08 02:39:12 -08001004 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 count = 0;
1006 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08001007 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 memcpy(head, chbuf, stlen);
1009 len -= stlen;
1010 chbuf += stlen;
1011 count += stlen;
1012 head += stlen;
1013 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1014 head = portp->tx.buf;
1015 stlen = tail - head;
1016 }
1017 }
1018 portp->tx.head = head;
1019
1020 clear_bit(ASYI_TXLOW, &portp->istate);
1021 stl_startrxtx(portp, -1, 1);
1022
Jesper Juhl014c2542006-01-15 02:37:08 +01001023 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024}
1025
1026/*****************************************************************************/
1027
David Howells4a561222008-07-22 11:18:43 +01001028static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001030 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 unsigned int len;
1032 char *head, *tail;
1033
Jiri Slabya0564e12006-12-08 02:38:37 -08001034 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Jiri Slaby615e4a72006-12-08 02:38:38 -08001036 if (tty == NULL)
David Howells4a561222008-07-22 11:18:43 +01001037 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001039 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001040 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001041 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +01001042 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 head = portp->tx.head;
1045 tail = portp->tx.tail;
1046
1047 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1048 len--;
1049
1050 if (len > 0) {
1051 *head++ = ch;
1052 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1053 head = portp->tx.buf;
1054 }
1055 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +01001056 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057}
1058
1059/*****************************************************************************/
1060
1061/*
1062 * If there are any characters in the buffer then make sure that TX
1063 * interrupts are on and get'em out. Normally used after the putchar
1064 * routine has been called.
1065 */
1066
1067static void stl_flushchars(struct tty_struct *tty)
1068{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001069 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Jiri Slabya0564e12006-12-08 02:38:37 -08001071 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return;
1075 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001076 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001078 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 return;
1080
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 stl_startrxtx(portp, -1, 1);
1082}
1083
1084/*****************************************************************************/
1085
1086static int stl_writeroom(struct tty_struct *tty)
1087{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001088 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 char *head, *tail;
1090
Jiri Slabya0564e12006-12-08 02:38:37 -08001091 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Jiri Slaby615e4a72006-12-08 02:38:38 -08001093 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001094 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001096 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001097 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001098 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001099 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
1101 head = portp->tx.head;
1102 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001103 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104}
1105
1106/*****************************************************************************/
1107
1108/*
1109 * Return number of chars in the TX buffer. Normally we would just
1110 * calculate the number of chars in the buffer and return that, but if
1111 * the buffer is empty and TX interrupts are still on then we return
1112 * that the buffer still has 1 char in it. This way whoever called us
1113 * will not think that ALL chars have drained - since the UART still
1114 * must have some chars in it (we are busy after all).
1115 */
1116
1117static int stl_charsinbuffer(struct tty_struct *tty)
1118{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001119 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 unsigned int size;
1121 char *head, *tail;
1122
Jiri Slabya0564e12006-12-08 02:38:37 -08001123 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Jiri Slaby615e4a72006-12-08 02:38:38 -08001125 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001126 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001128 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001129 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001130 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001131 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
1133 head = portp->tx.head;
1134 tail = portp->tx.tail;
1135 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1136 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1137 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001138 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139}
1140
1141/*****************************************************************************/
1142
1143/*
1144 * Generate the serial struct info.
1145 */
1146
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001147static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
1149 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001150 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Jiri Slabya0564e12006-12-08 02:38:37 -08001152 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 memset(&sio, 0, sizeof(struct serial_struct));
1155 sio.line = portp->portnr;
1156 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001157 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 sio.baud_base = portp->baud_base;
1159 sio.close_delay = portp->close_delay;
1160 sio.closing_wait = portp->closing_wait;
1161 sio.custom_divisor = portp->custom_divisor;
1162 sio.hub6 = 0;
1163 if (portp->uartp == &stl_cd1400uart) {
1164 sio.type = PORT_CIRRUS;
1165 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1166 } else {
1167 sio.type = PORT_UNKNOWN;
1168 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1169 }
1170
1171 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001172 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 sio.irq = brdp->irq;
1174
1175 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1176}
1177
1178/*****************************************************************************/
1179
1180/*
1181 * Set port according to the serial struct info.
1182 * At this point we do not do any auto-configure stuff, so we will
1183 * just quietly ignore any requests to change irq, etc.
1184 */
1185
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001186static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187{
1188 struct serial_struct sio;
1189
Jiri Slabya0564e12006-12-08 02:38:37 -08001190 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
1192 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1193 return -EFAULT;
1194 if (!capable(CAP_SYS_ADMIN)) {
1195 if ((sio.baud_base != portp->baud_base) ||
1196 (sio.close_delay != portp->close_delay) ||
1197 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001198 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001199 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 }
1201
Alan Coxf8ae4762008-07-16 21:56:37 +01001202 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 (sio.flags & ASYNC_USR_MASK);
1204 portp->baud_base = sio.baud_base;
1205 portp->close_delay = sio.close_delay;
1206 portp->closing_wait = sio.closing_wait;
1207 portp->custom_divisor = sio.custom_divisor;
Alan Coxf8ae4762008-07-16 21:56:37 +01001208 stl_setport(portp, portp->port.tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001209 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210}
1211
1212/*****************************************************************************/
1213
1214static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1215{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001216 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Jiri Slaby615e4a72006-12-08 02:38:38 -08001218 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001219 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001221 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001222 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001224 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 return stl_getsignals(portp);
1227}
1228
1229static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1230 unsigned int set, unsigned int clear)
1231{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001232 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 int rts = -1, dtr = -1;
1234
Jiri Slaby615e4a72006-12-08 02:38:38 -08001235 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001236 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001238 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001239 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001241 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 if (set & TIOCM_RTS)
1244 rts = 1;
1245 if (set & TIOCM_DTR)
1246 dtr = 1;
1247 if (clear & TIOCM_RTS)
1248 rts = 0;
1249 if (clear & TIOCM_DTR)
1250 dtr = 0;
1251
1252 stl_setsignals(portp, dtr, rts);
1253 return 0;
1254}
1255
1256static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1257{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001258 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 int rc;
1260 void __user *argp = (void __user *)arg;
1261
Jiri Slabya0564e12006-12-08 02:38:37 -08001262 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1263 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Jiri Slaby615e4a72006-12-08 02:38:38 -08001265 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001266 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001268 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001269 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001272 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001274 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 rc = 0;
1277
Alan Coxf433c652008-04-30 00:53:23 -07001278 lock_kernel();
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 case TIOCGSERIAL:
1282 rc = stl_getserial(portp, argp);
1283 break;
1284 case TIOCSSERIAL:
1285 rc = stl_setserial(portp, argp);
1286 break;
1287 case COM_GETPORTSTATS:
1288 rc = stl_getportstats(portp, argp);
1289 break;
1290 case COM_CLRPORTSTATS:
1291 rc = stl_clrportstats(portp, argp);
1292 break;
1293 case TIOCSERCONFIG:
1294 case TIOCSERGWILD:
1295 case TIOCSERSWILD:
1296 case TIOCSERGETLSR:
1297 case TIOCSERGSTRUCT:
1298 case TIOCSERGETMULTI:
1299 case TIOCSERSETMULTI:
1300 default:
1301 rc = -ENOIOCTLCMD;
1302 break;
1303 }
Alan Coxf433c652008-04-30 00:53:23 -07001304 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306}
1307
1308/*****************************************************************************/
1309
Jiri Slaby96b066b2006-12-08 02:38:42 -08001310/*
1311 * Start the transmitter again. Just turn TX interrupts back on.
1312 */
1313
1314static void stl_start(struct tty_struct *tty)
1315{
1316 struct stlport *portp;
1317
1318 pr_debug("stl_start(tty=%p)\n", tty);
1319
1320 if (tty == NULL)
1321 return;
1322 portp = tty->driver_data;
1323 if (portp == NULL)
1324 return;
1325 stl_startrxtx(portp, -1, 1);
1326}
1327
1328/*****************************************************************************/
1329
Alan Cox606d0992006-12-08 02:38:45 -08001330static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001332 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001333 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Jiri Slabya0564e12006-12-08 02:38:37 -08001335 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Jiri Slaby615e4a72006-12-08 02:38:38 -08001337 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return;
1339 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001340 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return;
1342
1343 tiosp = tty->termios;
1344 if ((tiosp->c_cflag == old->c_cflag) &&
1345 (tiosp->c_iflag == old->c_iflag))
1346 return;
1347
1348 stl_setport(portp, tiosp);
1349 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1350 -1);
1351 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1352 tty->hw_stopped = 0;
1353 stl_start(tty);
1354 }
1355 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001356 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357}
1358
1359/*****************************************************************************/
1360
1361/*
1362 * Attempt to flow control who ever is sending us data. Based on termios
1363 * settings use software or/and hardware flow control.
1364 */
1365
1366static void stl_throttle(struct tty_struct *tty)
1367{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001368 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slabya0564e12006-12-08 02:38:37 -08001370 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Jiri Slaby615e4a72006-12-08 02:38:38 -08001372 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return;
1374 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001375 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 return;
1377 stl_flowctrl(portp, 0);
1378}
1379
1380/*****************************************************************************/
1381
1382/*
1383 * Unflow control the device sending us data...
1384 */
1385
1386static void stl_unthrottle(struct tty_struct *tty)
1387{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001388 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Jiri Slabya0564e12006-12-08 02:38:37 -08001390 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Jiri Slaby615e4a72006-12-08 02:38:38 -08001392 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return;
1394 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001395 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 return;
1397 stl_flowctrl(portp, 1);
1398}
1399
1400/*****************************************************************************/
1401
1402/*
1403 * Stop the transmitter. Basically to do this we will just turn TX
1404 * interrupts off.
1405 */
1406
1407static void stl_stop(struct tty_struct *tty)
1408{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001409 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Jiri Slabya0564e12006-12-08 02:38:37 -08001411 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Jiri Slaby615e4a72006-12-08 02:38:38 -08001413 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 return;
1415 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001416 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return;
1418 stl_startrxtx(portp, -1, 0);
1419}
1420
1421/*****************************************************************************/
1422
1423/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 * Hangup this port. This is pretty much like closing the port, only
1425 * a little more brutal. No waiting for data to drain. Shutdown the
1426 * port and maybe drop signals.
1427 */
1428
1429static void stl_hangup(struct tty_struct *tty)
1430{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001431 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Jiri Slabya0564e12006-12-08 02:38:37 -08001433 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Jiri Slaby615e4a72006-12-08 02:38:38 -08001435 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return;
1437 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001438 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return;
1440
Alan Coxf8ae4762008-07-16 21:56:37 +01001441 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 stl_disableintrs(portp);
1443 if (tty->termios->c_cflag & HUPCL)
1444 stl_setsignals(portp, 0, 0);
1445 stl_enablerxtx(portp, 0, 0);
1446 stl_flushbuffer(tty);
1447 portp->istate = 0;
1448 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001449 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001451 portp->tx.buf = NULL;
1452 portp->tx.head = NULL;
1453 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Alan Coxf8ae4762008-07-16 21:56:37 +01001455 portp->port.tty = NULL;
1456 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1457 portp->port.count = 0;
1458 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459}
1460
1461/*****************************************************************************/
1462
David Howells4a561222008-07-22 11:18:43 +01001463static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jiri Slabya0564e12006-12-08 02:38:37 -08001467 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (tty == NULL)
David Howells4a561222008-07-22 11:18:43 +01001470 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001472 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001473 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001476 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477}
1478
1479/*****************************************************************************/
1480
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481static void stl_sendxchar(struct tty_struct *tty, char ch)
1482{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001483 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Jiri Slabya0564e12006-12-08 02:38:37 -08001485 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Jiri Slaby615e4a72006-12-08 02:38:38 -08001487 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 return;
1489 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001490 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 return;
1492
1493 if (ch == STOP_CHAR(tty))
1494 stl_sendflow(portp, 0);
1495 else if (ch == START_CHAR(tty))
1496 stl_sendflow(portp, 1);
1497 else
1498 stl_putchar(tty, ch);
1499}
1500
1501/*****************************************************************************/
1502
1503#define MAXLINE 80
1504
1505/*
1506 * Format info for a specified port. The line is deliberately limited
1507 * to 80 characters. (If it is too long it will be truncated, if too
1508 * short then padded with spaces).
1509 */
1510
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001511static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 char *sp;
1514 int sigs, cnt;
1515
1516 sp = pos;
1517 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1518 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1519 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1520
1521 if (portp->stats.rxframing)
1522 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1523 if (portp->stats.rxparity)
1524 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1525 if (portp->stats.rxbreaks)
1526 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1527 if (portp->stats.rxoverrun)
1528 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1529
1530 sigs = stl_getsignals(portp);
1531 cnt = sprintf(sp, "%s%s%s%s%s ",
1532 (sigs & TIOCM_RTS) ? "|RTS" : "",
1533 (sigs & TIOCM_CTS) ? "|CTS" : "",
1534 (sigs & TIOCM_DTR) ? "|DTR" : "",
1535 (sigs & TIOCM_CD) ? "|DCD" : "",
1536 (sigs & TIOCM_DSR) ? "|DSR" : "");
1537 *sp = ' ';
1538 sp += cnt;
1539
Jiri Slabyc62429d2006-12-08 02:39:14 -08001540 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 *sp++ = ' ';
1542 if (cnt >= MAXLINE)
1543 pos[(MAXLINE - 2)] = '+';
1544 pos[(MAXLINE - 1)] = '\n';
1545
Jesper Juhl014c2542006-01-15 02:37:08 +01001546 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547}
1548
1549/*****************************************************************************/
1550
1551/*
1552 * Port info, read from the /proc file system.
1553 */
1554
1555static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1556{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001557 struct stlbrd *brdp;
1558 struct stlpanel *panelp;
1559 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001560 unsigned int brdnr, panelnr, portnr;
1561 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 char *pos;
1563
Jiri Slabya0564e12006-12-08 02:38:37 -08001564 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1565 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 pos = page;
1568 totalport = 0;
1569 curoff = 0;
1570
1571 if (off == 0) {
1572 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1573 stl_drvversion);
1574 while (pos < (page + MAXLINE - 1))
1575 *pos++ = ' ';
1576 *pos++ = '\n';
1577 }
1578 curoff = MAXLINE;
1579
1580/*
1581 * We scan through for each board, panel and port. The offset is
1582 * calculated on the fly, and irrelevant ports are skipped.
1583 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001584 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001586 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 continue;
1588 if (brdp->state == 0)
1589 continue;
1590
1591 maxoff = curoff + (brdp->nrports * MAXLINE);
1592 if (off >= maxoff) {
1593 curoff = maxoff;
1594 continue;
1595 }
1596
1597 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001598 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001600 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 continue;
1602
1603 maxoff = curoff + (panelp->nrports * MAXLINE);
1604 if (off >= maxoff) {
1605 curoff = maxoff;
1606 totalport += panelp->nrports;
1607 continue;
1608 }
1609
Jiri Slabyc62429d2006-12-08 02:39:14 -08001610 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 totalport++) {
1612 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001613 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 continue;
1615 if (off >= (curoff += MAXLINE))
1616 continue;
1617 if ((pos - page + MAXLINE) > count)
1618 goto stl_readdone;
1619 pos += stl_portinfo(portp, totalport, pos);
1620 }
1621 }
1622 }
1623
1624 *eof = 1;
1625
1626stl_readdone:
1627 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001628 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
1631/*****************************************************************************/
1632
1633/*
1634 * All board interrupts are vectored through here first. This code then
1635 * calls off to the approrpriate board interrupt handlers.
1636 */
1637
David Howells7d12e782006-10-05 14:55:46 +01001638static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001640 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Jeff Garzika6f97b22007-10-31 05:20:49 -04001642 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 return IRQ_RETVAL((* brdp->isr)(brdp));
1645}
1646
1647/*****************************************************************************/
1648
1649/*
1650 * Interrupt service routine for EasyIO board types.
1651 */
1652
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001653static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001655 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 unsigned int iobase;
1657 int handled = 0;
1658
Alan Coxb65b5b52006-06-27 02:54:05 -07001659 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 panelp = brdp->panels[0];
1661 iobase = panelp->iobase;
1662 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1663 handled = 1;
1664 (* panelp->isr)(panelp, iobase);
1665 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001666 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667 return handled;
1668}
1669
1670/*****************************************************************************/
1671
1672/*
1673 * Interrupt service routine for ECH-AT board types.
1674 */
1675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001676static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001678 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001679 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 int handled = 0;
1681
1682 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1683
1684 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1685 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001686 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 ioaddr = brdp->bnkstataddr[bnknr];
1688 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1689 panelp = brdp->bnk2panel[bnknr];
1690 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1691 }
1692 }
1693 }
1694
1695 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1696
1697 return handled;
1698}
1699
1700/*****************************************************************************/
1701
1702/*
1703 * Interrupt service routine for ECH-MCA board types.
1704 */
1705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001706static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001708 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001709 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 int handled = 0;
1711
1712 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1713 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001714 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 ioaddr = brdp->bnkstataddr[bnknr];
1716 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1717 panelp = brdp->bnk2panel[bnknr];
1718 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1719 }
1720 }
1721 }
1722 return handled;
1723}
1724
1725/*****************************************************************************/
1726
1727/*
1728 * Interrupt service routine for ECH-PCI board types.
1729 */
1730
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001731static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001733 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001734 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 int handled = 0;
1736
1737 while (1) {
1738 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001739 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1741 ioaddr = brdp->bnkstataddr[bnknr];
1742 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1743 panelp = brdp->bnk2panel[bnknr];
1744 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1745 recheck++;
1746 handled = 1;
1747 }
1748 }
1749 if (! recheck)
1750 break;
1751 }
1752 return handled;
1753}
1754
1755/*****************************************************************************/
1756
1757/*
1758 * Interrupt service routine for ECH-8/64-PCI board types.
1759 */
1760
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001761static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001763 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001764 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 int handled = 0;
1766
1767 while (inb(brdp->ioctrl) & 0x1) {
1768 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001769 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 ioaddr = brdp->bnkstataddr[bnknr];
1771 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1772 panelp = brdp->bnk2panel[bnknr];
1773 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1774 }
1775 }
1776 }
1777
1778 return handled;
1779}
1780
1781/*****************************************************************************/
1782
1783/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 * Initialize all the ports on a panel.
1785 */
1786
Jiri Slaby705c1862006-12-08 02:39:11 -08001787static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001789 struct stlport *portp;
1790 unsigned int i;
1791 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792
Jiri Slabya0564e12006-12-08 02:38:37 -08001793 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
1795 chipmask = stl_panelinit(brdp, panelp);
1796
1797/*
1798 * All UART's are initialized (if found!). Now go through and setup
1799 * each ports data structures.
1800 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001801 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001802 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001803 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001805 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 break;
1807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
1809 portp->magic = STL_PORTMAGIC;
1810 portp->portnr = i;
1811 portp->brdnr = panelp->brdnr;
1812 portp->panelnr = panelp->panelnr;
1813 portp->uartp = panelp->uartp;
1814 portp->clk = brdp->clk;
1815 portp->baud_base = STL_BAUDBASE;
1816 portp->close_delay = STL_CLOSEDELAY;
1817 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001818 init_waitqueue_head(&portp->port.open_wait);
1819 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 portp->stats.brd = portp->brdnr;
1821 portp->stats.panel = portp->panelnr;
1822 portp->stats.port = portp->portnr;
1823 panelp->ports[i] = portp;
1824 stl_portinit(brdp, panelp, portp);
1825 }
1826
Jiri Slabyc62429d2006-12-08 02:39:14 -08001827 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828}
1829
Jiri Slaby3b85b342006-12-08 02:39:10 -08001830static void stl_cleanup_panels(struct stlbrd *brdp)
1831{
1832 struct stlpanel *panelp;
1833 struct stlport *portp;
1834 unsigned int j, k;
1835
1836 for (j = 0; j < STL_MAXPANELS; j++) {
1837 panelp = brdp->panels[j];
1838 if (panelp == NULL)
1839 continue;
1840 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1841 portp = panelp->ports[k];
1842 if (portp == NULL)
1843 continue;
Alan Coxf8ae4762008-07-16 21:56:37 +01001844 if (portp->port.tty != NULL)
1845 stl_hangup(portp->port.tty);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001846 kfree(portp->tx.buf);
1847 kfree(portp);
1848 }
1849 kfree(panelp);
1850 }
1851}
1852
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853/*****************************************************************************/
1854
1855/*
1856 * Try to find and initialize an EasyIO board.
1857 */
1858
Jiri Slaby705c1862006-12-08 02:39:11 -08001859static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001861 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 unsigned int status;
1863 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001864 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Jiri Slabya0564e12006-12-08 02:38:37 -08001866 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
1868 brdp->ioctrl = brdp->ioaddr1 + 1;
1869 brdp->iostatus = brdp->ioaddr1 + 2;
1870
1871 status = inb(brdp->iostatus);
1872 if ((status & EIO_IDBITMASK) == EIO_MK3)
1873 brdp->ioctrl++;
1874
1875/*
1876 * Handle board specific stuff now. The real difference is PCI
1877 * or not PCI.
1878 */
1879 if (brdp->brdtype == BRD_EASYIOPCI) {
1880 brdp->iosize1 = 0x80;
1881 brdp->iosize2 = 0x80;
1882 name = "serial(EIO-PCI)";
1883 outb(0x41, (brdp->ioaddr2 + 0x4c));
1884 } else {
1885 brdp->iosize1 = 8;
1886 name = "serial(EIO)";
1887 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1888 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1889 printk("STALLION: invalid irq=%d for brd=%d\n",
1890 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001891 retval = -EINVAL;
1892 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 }
1894 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1895 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1896 brdp->ioctrl);
1897 }
1898
Jiri Slaby3b85b342006-12-08 02:39:10 -08001899 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1901 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1902 "%x conflicts with another device\n", brdp->brdnr,
1903 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001904 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 }
1906
1907 if (brdp->iosize2 > 0)
1908 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1909 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1910 "address %x conflicts with another device\n",
1911 brdp->brdnr, brdp->ioaddr2);
1912 printk(KERN_WARNING "STALLION: Warning, also "
1913 "releasing board %d I/O address %x \n",
1914 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001915 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 }
1917
1918/*
1919 * Everything looks OK, so let's go ahead and probe for the hardware.
1920 */
1921 brdp->clk = CD1400_CLK;
1922 brdp->isr = stl_eiointr;
1923
Jiri Slaby3b85b342006-12-08 02:39:10 -08001924 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 switch (status & EIO_IDBITMASK) {
1926 case EIO_8PORTM:
1927 brdp->clk = CD1400_CLK8M;
1928 /* fall thru */
1929 case EIO_8PORTRS:
1930 case EIO_8PORTDI:
1931 brdp->nrports = 8;
1932 break;
1933 case EIO_4PORTRS:
1934 brdp->nrports = 4;
1935 break;
1936 case EIO_MK3:
1937 switch (status & EIO_BRDMASK) {
1938 case ID_BRD4:
1939 brdp->nrports = 4;
1940 break;
1941 case ID_BRD8:
1942 brdp->nrports = 8;
1943 break;
1944 case ID_BRD16:
1945 brdp->nrports = 16;
1946 break;
1947 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001948 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 }
1950 break;
1951 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001952 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 }
1954
1955/*
1956 * We have verified that the board is actually present, so now we
1957 * can complete the setup.
1958 */
1959
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001960 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001961 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001963 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001964 retval = -ENOMEM;
1965 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
1968 panelp->magic = STL_PANELMAGIC;
1969 panelp->brdnr = brdp->brdnr;
1970 panelp->panelnr = 0;
1971 panelp->nrports = brdp->nrports;
1972 panelp->iobase = brdp->ioaddr1;
1973 panelp->hwid = status;
1974 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001975 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 panelp->isr = stl_sc26198intr;
1977 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001978 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 panelp->isr = stl_cd1400eiointr;
1980 }
1981
1982 brdp->panels[0] = panelp;
1983 brdp->nrpanels = 1;
1984 brdp->state |= BRD_FOUND;
1985 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001986 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 printk("STALLION: failed to register interrupt "
1988 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001989 retval = -ENODEV;
1990 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001992
1993 return 0;
1994err_fr:
1995 stl_cleanup_panels(brdp);
1996err_rel2:
1997 if (brdp->iosize2 > 0)
1998 release_region(brdp->ioaddr2, brdp->iosize2);
1999err_rel1:
2000 release_region(brdp->ioaddr1, brdp->iosize1);
2001err:
2002 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003}
2004
2005/*****************************************************************************/
2006
2007/*
2008 * Try to find an ECH board and initialize it. This code is capable of
2009 * dealing with all types of ECH board.
2010 */
2011
Jiri Slaby705c1862006-12-08 02:39:11 -08002012static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002014 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002015 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2016 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 char *name;
2018
Jiri Slabya0564e12006-12-08 02:38:37 -08002019 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
2021 status = 0;
2022 conflict = 0;
2023
2024/*
2025 * Set up the initial board register contents for boards. This varies a
2026 * bit between the different board types. So we need to handle each
2027 * separately. Also do a check that the supplied IRQ is good.
2028 */
2029 switch (brdp->brdtype) {
2030
2031 case BRD_ECH:
2032 brdp->isr = stl_echatintr;
2033 brdp->ioctrl = brdp->ioaddr1 + 1;
2034 brdp->iostatus = brdp->ioaddr1 + 1;
2035 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002036 if ((status & ECH_IDBITMASK) != ECH_ID) {
2037 retval = -ENODEV;
2038 goto err;
2039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2041 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2042 printk("STALLION: invalid irq=%d for brd=%d\n",
2043 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002044 retval = -EINVAL;
2045 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 }
2047 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2048 status |= (stl_vecmap[brdp->irq] << 1);
2049 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2050 brdp->ioctrlval = ECH_INTENABLE |
2051 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002052 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2054 brdp->iosize1 = 2;
2055 brdp->iosize2 = 32;
2056 name = "serial(EC8/32)";
2057 outb(status, brdp->ioaddr1);
2058 break;
2059
2060 case BRD_ECHMC:
2061 brdp->isr = stl_echmcaintr;
2062 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2063 brdp->iostatus = brdp->ioctrl;
2064 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002065 if ((status & ECH_IDBITMASK) != ECH_ID) {
2066 retval = -ENODEV;
2067 goto err;
2068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2070 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2071 printk("STALLION: invalid irq=%d for brd=%d\n",
2072 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002073 retval = -EINVAL;
2074 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 }
2076 outb(ECHMC_BRDRESET, brdp->ioctrl);
2077 outb(ECHMC_INTENABLE, brdp->ioctrl);
2078 brdp->iosize1 = 64;
2079 name = "serial(EC8/32-MC)";
2080 break;
2081
2082 case BRD_ECHPCI:
2083 brdp->isr = stl_echpciintr;
2084 brdp->ioctrl = brdp->ioaddr1 + 2;
2085 brdp->iosize1 = 4;
2086 brdp->iosize2 = 8;
2087 name = "serial(EC8/32-PCI)";
2088 break;
2089
2090 case BRD_ECH64PCI:
2091 brdp->isr = stl_echpci64intr;
2092 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2093 outb(0x43, (brdp->ioaddr1 + 0x4c));
2094 brdp->iosize1 = 0x80;
2095 brdp->iosize2 = 0x80;
2096 name = "serial(EC8/64-PCI)";
2097 break;
2098
2099 default:
2100 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002101 retval = -EINVAL;
2102 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
2104
2105/*
2106 * Check boards for possible IO address conflicts and return fail status
2107 * if an IO conflict found.
2108 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002109 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2111 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2112 "%x conflicts with another device\n", brdp->brdnr,
2113 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002114 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 }
2116
2117 if (brdp->iosize2 > 0)
2118 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2119 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2120 "address %x conflicts with another device\n",
2121 brdp->brdnr, brdp->ioaddr2);
2122 printk(KERN_WARNING "STALLION: Warning, also "
2123 "releasing board %d I/O address %x \n",
2124 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002125 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
2127
2128/*
2129 * Scan through the secondary io address space looking for panels.
2130 * As we find'em allocate and initialize panel structures for each.
2131 */
2132 brdp->clk = CD1400_CLK;
2133 brdp->hwid = status;
2134
2135 ioaddr = brdp->ioaddr2;
2136 banknr = 0;
2137 panelnr = 0;
2138 nxtid = 0;
2139
Jiri Slabyc62429d2006-12-08 02:39:14 -08002140 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 if (brdp->brdtype == BRD_ECHPCI) {
2142 outb(nxtid, brdp->ioctrl);
2143 ioaddr = brdp->ioaddr2;
2144 }
2145 status = inb(ioaddr + ECH_PNLSTATUS);
2146 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002147 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002148 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002149 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002151 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002152 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002153 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 panelp->magic = STL_PANELMAGIC;
2156 panelp->brdnr = brdp->brdnr;
2157 panelp->panelnr = panelnr;
2158 panelp->iobase = ioaddr;
2159 panelp->pagenr = nxtid;
2160 panelp->hwid = status;
2161 brdp->bnk2panel[banknr] = panelp;
2162 brdp->bnkpageaddr[banknr] = nxtid;
2163 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2164
2165 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002166 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 panelp->isr = stl_sc26198intr;
2168 if (status & ECH_PNL16PORT) {
2169 panelp->nrports = 16;
2170 brdp->bnk2panel[banknr] = panelp;
2171 brdp->bnkpageaddr[banknr] = nxtid;
2172 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2173 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002174 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002177 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 panelp->isr = stl_cd1400echintr;
2179 if (status & ECH_PNL16PORT) {
2180 panelp->nrports = 16;
2181 panelp->ackmask = 0x80;
2182 if (brdp->brdtype != BRD_ECHPCI)
2183 ioaddr += EREG_BANKSIZE;
2184 brdp->bnk2panel[banknr] = panelp;
2185 brdp->bnkpageaddr[banknr] = ++nxtid;
2186 brdp->bnkstataddr[banknr++] = ioaddr +
2187 ECH_PNLSTATUS;
2188 } else {
2189 panelp->nrports = 8;
2190 panelp->ackmask = 0xc0;
2191 }
2192 }
2193
2194 nxtid++;
2195 ioaddr += EREG_BANKSIZE;
2196 brdp->nrports += panelp->nrports;
2197 brdp->panels[panelnr++] = panelp;
2198 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002199 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2200 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002201 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 }
2204
2205 brdp->nrpanels = panelnr;
2206 brdp->nrbnks = banknr;
2207 if (brdp->brdtype == BRD_ECH)
2208 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2209
2210 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002211 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 printk("STALLION: failed to register interrupt "
2213 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002214 retval = -ENODEV;
2215 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 }
2217
Jiri Slaby3b85b342006-12-08 02:39:10 -08002218 return 0;
2219err_fr:
2220 stl_cleanup_panels(brdp);
2221 if (brdp->iosize2 > 0)
2222 release_region(brdp->ioaddr2, brdp->iosize2);
2223err_rel1:
2224 release_region(brdp->ioaddr1, brdp->iosize1);
2225err:
2226 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227}
2228
2229/*****************************************************************************/
2230
2231/*
2232 * Initialize and configure the specified board.
2233 * Scan through all the boards in the configuration and see what we
2234 * can find. Handle EIO and the ECH boards a little differently here
2235 * since the initial search and setup is very different.
2236 */
2237
Jiri Slaby705c1862006-12-08 02:39:11 -08002238static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002240 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241
Jiri Slabya0564e12006-12-08 02:38:37 -08002242 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 switch (brdp->brdtype) {
2245 case BRD_EASYIO:
2246 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002247 retval = stl_initeio(brdp);
2248 if (retval)
2249 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 break;
2251 case BRD_ECH:
2252 case BRD_ECHMC:
2253 case BRD_ECHPCI:
2254 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002255 retval = stl_initech(brdp);
2256 if (retval)
2257 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 break;
2259 default:
2260 printk("STALLION: board=%d is unknown board type=%d\n",
2261 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002262 retval = -ENODEV;
2263 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 }
2265
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 if ((brdp->state & BRD_FOUND) == 0) {
2267 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2268 stl_brdnames[brdp->brdtype], brdp->brdnr,
2269 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002270 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 }
2272
Jiri Slabyc62429d2006-12-08 02:39:14 -08002273 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002274 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 stl_initports(brdp, brdp->panels[i]);
2276
2277 printk("STALLION: %s found, board=%d io=%x irq=%d "
2278 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2279 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2280 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002281
2282 return 0;
2283err_free:
2284 free_irq(brdp->irq, brdp);
2285
2286 stl_cleanup_panels(brdp);
2287
2288 release_region(brdp->ioaddr1, brdp->iosize1);
2289 if (brdp->iosize2 > 0)
2290 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002291err:
2292 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293}
2294
2295/*****************************************************************************/
2296
2297/*
2298 * Find the next available board number that is free.
2299 */
2300
Jiri Slaby705c1862006-12-08 02:39:11 -08002301static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002303 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Jiri Slabyc62429d2006-12-08 02:39:14 -08002305 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002306 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 if (i >= stl_nrbrds)
2308 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002309 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002311
2312 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313}
2314
2315/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316/*
2317 * We have a Stallion board. Allocate a board structure and
2318 * initialize it. Read its IO and IRQ resources from PCI
2319 * configuration space.
2320 */
2321
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002322static int __devinit stl_pciprobe(struct pci_dev *pdev,
2323 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002325 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002326 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002327 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002329 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002330 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002331
Jiri Slaby3b85b342006-12-08 02:39:10 -08002332 retval = pci_enable_device(pdev);
2333 if (retval)
2334 goto err;
2335 brdp = stl_allocbrd();
2336 if (brdp == NULL) {
2337 retval = -ENOMEM;
2338 goto err;
2339 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002340 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002341 brdnr = stl_getbrdnr();
2342 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002343 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002345 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002346 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002347 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002349 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002350 stl_brds[brdp->brdnr] = brdp;
2351 mutex_unlock(&stl_brdslock);
2352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002354 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
2356/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 * We have all resources from the board, so let's setup the actual
2358 * board structure now.
2359 */
2360 switch (brdtype) {
2361 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002362 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2363 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 break;
2365 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002366 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2367 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 break;
2369 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002370 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2371 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 break;
2373 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002374 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 break;
2376 }
2377
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002378 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002379 retval = stl_brdinit(brdp);
2380 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002381 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002383 pci_set_drvdata(pdev, brdp);
2384
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002385 for (i = 0; i < brdp->nrports; i++)
2386 tty_register_device(stl_serial,
2387 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2388
Jiri Slaby3b85b342006-12-08 02:39:10 -08002389 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002390err_null:
2391 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002392err_fr:
2393 kfree(brdp);
2394err:
2395 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396}
2397
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002398static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002400 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002401 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002403 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002405 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002407 release_region(brdp->ioaddr1, brdp->iosize1);
2408 if (brdp->iosize2 > 0)
2409 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002411 for (i = 0; i < brdp->nrports; i++)
2412 tty_unregister_device(stl_serial,
2413 brdp->brdnr * STL_MAXPORTS + i);
2414
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002415 stl_brds[brdp->brdnr] = NULL;
2416 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417}
2418
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002419static struct pci_driver stl_pcidriver = {
2420 .name = "stallion",
2421 .id_table = stl_pcibrds,
2422 .probe = stl_pciprobe,
2423 .remove = __devexit_p(stl_pciremove)
2424};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
2426/*****************************************************************************/
2427
2428/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 * Return the board stats structure to user app.
2430 */
2431
2432static int stl_getbrdstats(combrd_t __user *bp)
2433{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002434 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002435 struct stlbrd *brdp;
2436 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002437 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
2439 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2440 return -EFAULT;
2441 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002442 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002444 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002445 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446
2447 memset(&stl_brdstats, 0, sizeof(combrd_t));
2448 stl_brdstats.brd = brdp->brdnr;
2449 stl_brdstats.type = brdp->brdtype;
2450 stl_brdstats.hwid = brdp->hwid;
2451 stl_brdstats.state = brdp->state;
2452 stl_brdstats.ioaddr = brdp->ioaddr1;
2453 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2454 stl_brdstats.irq = brdp->irq;
2455 stl_brdstats.nrpanels = brdp->nrpanels;
2456 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002457 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 panelp = brdp->panels[i];
2459 stl_brdstats.panels[i].panel = i;
2460 stl_brdstats.panels[i].hwid = panelp->hwid;
2461 stl_brdstats.panels[i].nrports = panelp->nrports;
2462 }
2463
2464 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2465}
2466
2467/*****************************************************************************/
2468
2469/*
2470 * Resolve the referenced port number into a port struct pointer.
2471 */
2472
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002473static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002475 struct stlbrd *brdp;
2476 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Jiri Slabyc62429d2006-12-08 02:39:14 -08002478 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2479 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002481 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002482 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002483 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002484 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002486 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002487 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002488 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002489 return NULL;
2490 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491}
2492
2493/*****************************************************************************/
2494
2495/*
2496 * Return the port stats structure to user app. A NULL port struct
2497 * pointer passed in means that we need to find out from the app
2498 * what port to get stats for (used through board control device).
2499 */
2500
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002501static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002503 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 unsigned char *head, *tail;
2505 unsigned long flags;
2506
2507 if (!portp) {
2508 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2509 return -EFAULT;
2510 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2511 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002512 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002513 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 }
2515
2516 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002517 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 portp->stats.hwid = portp->hwid;
2519
2520 portp->stats.ttystate = 0;
2521 portp->stats.cflags = 0;
2522 portp->stats.iflags = 0;
2523 portp->stats.oflags = 0;
2524 portp->stats.lflags = 0;
2525 portp->stats.rxbuffered = 0;
2526
Alan Coxb65b5b52006-06-27 02:54:05 -07002527 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +01002528 if (portp->port.tty != NULL)
2529 if (portp->port.tty->driver_data == portp) {
2530 portp->stats.ttystate = portp->port.tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002531 /* No longer available as a statistic */
Alan Coxf8ae4762008-07-16 21:56:37 +01002532 portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
2533 if (portp->port.tty->termios != NULL) {
2534 portp->stats.cflags = portp->port.tty->termios->c_cflag;
2535 portp->stats.iflags = portp->port.tty->termios->c_iflag;
2536 portp->stats.oflags = portp->port.tty->termios->c_oflag;
2537 portp->stats.lflags = portp->port.tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 }
2539 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002540 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
2542 head = portp->tx.head;
2543 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002544 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2545 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
2547 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2548
2549 return copy_to_user(cp, &portp->stats,
2550 sizeof(comstats_t)) ? -EFAULT : 0;
2551}
2552
2553/*****************************************************************************/
2554
2555/*
2556 * Clear the port stats structure. We also return it zeroed out...
2557 */
2558
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002559static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002561 comstats_t stl_comstats;
2562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 if (!portp) {
2564 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2565 return -EFAULT;
2566 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2567 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002568 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002569 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 }
2571
2572 memset(&portp->stats, 0, sizeof(comstats_t));
2573 portp->stats.brd = portp->brdnr;
2574 portp->stats.panel = portp->panelnr;
2575 portp->stats.port = portp->portnr;
2576 return copy_to_user(cp, &portp->stats,
2577 sizeof(comstats_t)) ? -EFAULT : 0;
2578}
2579
2580/*****************************************************************************/
2581
2582/*
2583 * Return the entire driver ports structure to a user app.
2584 */
2585
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002586static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002588 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002589 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002591 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 return -EFAULT;
2593 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2594 stl_dummyport.portnr);
2595 if (!portp)
2596 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002597 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598}
2599
2600/*****************************************************************************/
2601
2602/*
2603 * Return the entire driver board structure to a user app.
2604 */
2605
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002606static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002608 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002609 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002611 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002613 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 return -ENODEV;
2615 brdp = stl_brds[stl_dummybrd.brdnr];
2616 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002617 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002618 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619}
2620
2621/*****************************************************************************/
2622
2623/*
2624 * The "staliomem" device is also required to do some special operations
2625 * on the board and/or ports. In this driver it is mostly used for stats
2626 * collection.
2627 */
2628
2629static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2630{
2631 int brdnr, rc;
2632 void __user *argp = (void __user *)arg;
2633
Jiri Slabya0564e12006-12-08 02:38:37 -08002634 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 brdnr = iminor(ip);
2637 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002638 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 rc = 0;
2640
2641 switch (cmd) {
2642 case COM_GETPORTSTATS:
2643 rc = stl_getportstats(NULL, argp);
2644 break;
2645 case COM_CLRPORTSTATS:
2646 rc = stl_clrportstats(NULL, argp);
2647 break;
2648 case COM_GETBRDSTATS:
2649 rc = stl_getbrdstats(argp);
2650 break;
2651 case COM_READPORT:
2652 rc = stl_getportstruct(argp);
2653 break;
2654 case COM_READBOARD:
2655 rc = stl_getbrdstruct(argp);
2656 break;
2657 default:
2658 rc = -ENOIOCTLCMD;
2659 break;
2660 }
2661
Jiri Slabyc62429d2006-12-08 02:39:14 -08002662 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663}
2664
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002665static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 .open = stl_open,
2667 .close = stl_close,
2668 .write = stl_write,
2669 .put_char = stl_putchar,
2670 .flush_chars = stl_flushchars,
2671 .write_room = stl_writeroom,
2672 .chars_in_buffer = stl_charsinbuffer,
2673 .ioctl = stl_ioctl,
2674 .set_termios = stl_settermios,
2675 .throttle = stl_throttle,
2676 .unthrottle = stl_unthrottle,
2677 .stop = stl_stop,
2678 .start = stl_start,
2679 .hangup = stl_hangup,
2680 .flush_buffer = stl_flushbuffer,
2681 .break_ctl = stl_breakctl,
2682 .wait_until_sent = stl_waituntilsent,
2683 .send_xchar = stl_sendxchar,
2684 .read_proc = stl_readproc,
2685 .tiocmget = stl_tiocmget,
2686 .tiocmset = stl_tiocmset,
2687};
2688
2689/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690/* CD1400 HARDWARE FUNCTIONS */
2691/*****************************************************************************/
2692
2693/*
2694 * These functions get/set/update the registers of the cd1400 UARTs.
2695 * Access to the cd1400 registers is via an address/data io port pair.
2696 * (Maybe should make this inline...)
2697 */
2698
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002699static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700{
2701 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002702 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703}
2704
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002705static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002707 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 outb(value, portp->ioaddr + EREG_DATA);
2709}
2710
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002711static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002713 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 if (inb(portp->ioaddr + EREG_DATA) != value) {
2715 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002716 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002718 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719}
2720
2721/*****************************************************************************/
2722
2723/*
2724 * Inbitialize the UARTs in a panel. We don't care what sort of board
2725 * these ports are on - since the port io registers are almost
2726 * identical when dealing with ports.
2727 */
2728
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002729static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730{
2731 unsigned int gfrcr;
2732 int chipmask, i, j;
2733 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002734 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735
Jiri Slabya0564e12006-12-08 02:38:37 -08002736 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
Alan Coxb65b5b52006-06-27 02:54:05 -07002738 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 BRDENABLE(panelp->brdnr, panelp->pagenr);
2740
2741/*
2742 * Check that each chip is present and started up OK.
2743 */
2744 chipmask = 0;
2745 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002746 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 if (brdp->brdtype == BRD_ECHPCI) {
2748 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2749 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002750 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 uartaddr = (i & 0x01) ? 0x080 : 0;
2753 outb((GFRCR + uartaddr), ioaddr);
2754 outb(0, (ioaddr + EREG_DATA));
2755 outb((CCR + uartaddr), ioaddr);
2756 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2757 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2758 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002759 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2761 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002762
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2764 printk("STALLION: cd1400 not responding, "
2765 "brd=%d panel=%d chip=%d\n",
2766 panelp->brdnr, panelp->panelnr, i);
2767 continue;
2768 }
2769 chipmask |= (0x1 << i);
2770 outb((PPR + uartaddr), ioaddr);
2771 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2772 }
2773
2774 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002775 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002776 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777}
2778
2779/*****************************************************************************/
2780
2781/*
2782 * Initialize hardware specific port registers.
2783 */
2784
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002785static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786{
Alan Coxb65b5b52006-06-27 02:54:05 -07002787 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002788 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2789 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790
Jiri Slaby615e4a72006-12-08 02:38:38 -08002791 if ((brdp == NULL) || (panelp == NULL) ||
2792 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 return;
2794
Alan Coxb65b5b52006-06-27 02:54:05 -07002795 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2797 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2798 portp->uartaddr = (portp->portnr & 0x04) << 5;
2799 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2800
2801 BRDENABLE(portp->brdnr, portp->pagenr);
2802 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2803 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2804 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2805 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002806 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807}
2808
2809/*****************************************************************************/
2810
2811/*
2812 * Wait for the command register to be ready. We will poll this,
2813 * since it won't usually take too long to be ready.
2814 */
2815
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002816static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817{
2818 int i;
2819
Jiri Slabyc62429d2006-12-08 02:39:14 -08002820 for (i = 0; i < CCR_MAXWAIT; i++)
2821 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
2824 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2825 portp->portnr, portp->panelnr, portp->brdnr);
2826}
2827
2828/*****************************************************************************/
2829
2830/*
2831 * Set up the cd1400 registers for a port based on the termios port
2832 * settings.
2833 */
2834
Alan Cox606d0992006-12-08 02:38:45 -08002835static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002837 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 unsigned long flags;
2839 unsigned int clkdiv, baudrate;
2840 unsigned char cor1, cor2, cor3;
2841 unsigned char cor4, cor5, ccr;
2842 unsigned char srer, sreron, sreroff;
2843 unsigned char mcor1, mcor2, rtpr;
2844 unsigned char clk, div;
2845
2846 cor1 = 0;
2847 cor2 = 0;
2848 cor3 = 0;
2849 cor4 = 0;
2850 cor5 = 0;
2851 ccr = 0;
2852 rtpr = 0;
2853 clk = 0;
2854 div = 0;
2855 mcor1 = 0;
2856 mcor2 = 0;
2857 sreron = 0;
2858 sreroff = 0;
2859
2860 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002861 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 return;
2863
2864/*
2865 * Set up the RX char ignore mask with those RX error types we
2866 * can ignore. We can get the cd1400 to help us out a little here,
2867 * it will ignore parity errors and breaks for us.
2868 */
2869 portp->rxignoremsk = 0;
2870 if (tiosp->c_iflag & IGNPAR) {
2871 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2872 cor1 |= COR1_PARIGNORE;
2873 }
2874 if (tiosp->c_iflag & IGNBRK) {
2875 portp->rxignoremsk |= ST_BREAK;
2876 cor4 |= COR4_IGNBRK;
2877 }
2878
2879 portp->rxmarkmsk = ST_OVERRUN;
2880 if (tiosp->c_iflag & (INPCK | PARMRK))
2881 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2882 if (tiosp->c_iflag & BRKINT)
2883 portp->rxmarkmsk |= ST_BREAK;
2884
2885/*
2886 * Go through the char size, parity and stop bits and set all the
2887 * option register appropriately.
2888 */
2889 switch (tiosp->c_cflag & CSIZE) {
2890 case CS5:
2891 cor1 |= COR1_CHL5;
2892 break;
2893 case CS6:
2894 cor1 |= COR1_CHL6;
2895 break;
2896 case CS7:
2897 cor1 |= COR1_CHL7;
2898 break;
2899 default:
2900 cor1 |= COR1_CHL8;
2901 break;
2902 }
2903
2904 if (tiosp->c_cflag & CSTOPB)
2905 cor1 |= COR1_STOP2;
2906 else
2907 cor1 |= COR1_STOP1;
2908
2909 if (tiosp->c_cflag & PARENB) {
2910 if (tiosp->c_cflag & PARODD)
2911 cor1 |= (COR1_PARENB | COR1_PARODD);
2912 else
2913 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2914 } else {
2915 cor1 |= COR1_PARNONE;
2916 }
2917
2918/*
2919 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2920 * space for hardware flow control and the like. This should be set to
2921 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2922 * really be based on VTIME.
2923 */
2924 cor3 |= FIFO_RXTHRESHOLD;
2925 rtpr = 2;
2926
2927/*
2928 * Calculate the baud rate timers. For now we will just assume that
2929 * the input and output baud are the same. Could have used a baud
2930 * table here, but this way we can generate virtually any baud rate
2931 * we like!
2932 */
2933 baudrate = tiosp->c_cflag & CBAUD;
2934 if (baudrate & CBAUDEX) {
2935 baudrate &= ~CBAUDEX;
2936 if ((baudrate < 1) || (baudrate > 4))
2937 tiosp->c_cflag &= ~CBAUDEX;
2938 else
2939 baudrate += 15;
2940 }
2941 baudrate = stl_baudrates[baudrate];
2942 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002943 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002945 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002947 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002949 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002951 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 baudrate = (portp->baud_base / portp->custom_divisor);
2953 }
2954 if (baudrate > STL_CD1400MAXBAUD)
2955 baudrate = STL_CD1400MAXBAUD;
2956
2957 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002958 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2959 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 if (clkdiv < 0x100)
2961 break;
2962 }
2963 div = (unsigned char) clkdiv;
2964 }
2965
2966/*
2967 * Check what form of modem signaling is required and set it up.
2968 */
2969 if ((tiosp->c_cflag & CLOCAL) == 0) {
2970 mcor1 |= MCOR1_DCD;
2971 mcor2 |= MCOR2_DCD;
2972 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002973 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002974 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002975 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
2977/*
2978 * Setup cd1400 enhanced modes if we can. In particular we want to
2979 * handle as much of the flow control as possible automatically. As
2980 * well as saving a few CPU cycles it will also greatly improve flow
2981 * control reliability.
2982 */
2983 if (tiosp->c_iflag & IXON) {
2984 cor2 |= COR2_TXIBE;
2985 cor3 |= COR3_SCD12;
2986 if (tiosp->c_iflag & IXANY)
2987 cor2 |= COR2_IXM;
2988 }
2989
2990 if (tiosp->c_cflag & CRTSCTS) {
2991 cor2 |= COR2_CTSAE;
2992 mcor1 |= FIFO_RTSTHRESHOLD;
2993 }
2994
2995/*
2996 * All cd1400 register values calculated so go through and set
2997 * them all up.
2998 */
2999
Jiri Slabya0564e12006-12-08 02:38:37 -08003000 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003002 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003004 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003006 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3007 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3009 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Alan Coxb65b5b52006-06-27 02:54:05 -07003011 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 BRDENABLE(portp->brdnr, portp->pagenr);
3013 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3014 srer = stl_cd1400getreg(portp, SRER);
3015 stl_cd1400setreg(portp, SRER, 0);
3016 if (stl_cd1400updatereg(portp, COR1, cor1))
3017 ccr = 1;
3018 if (stl_cd1400updatereg(portp, COR2, cor2))
3019 ccr = 1;
3020 if (stl_cd1400updatereg(portp, COR3, cor3))
3021 ccr = 1;
3022 if (ccr) {
3023 stl_cd1400ccrwait(portp);
3024 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3025 }
3026 stl_cd1400setreg(portp, COR4, cor4);
3027 stl_cd1400setreg(portp, COR5, cor5);
3028 stl_cd1400setreg(portp, MCOR1, mcor1);
3029 stl_cd1400setreg(portp, MCOR2, mcor2);
3030 if (baudrate > 0) {
3031 stl_cd1400setreg(portp, TCOR, clk);
3032 stl_cd1400setreg(portp, TBPR, div);
3033 stl_cd1400setreg(portp, RCOR, clk);
3034 stl_cd1400setreg(portp, RBPR, div);
3035 }
3036 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3037 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3038 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3039 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3040 stl_cd1400setreg(portp, RTPR, rtpr);
3041 mcor1 = stl_cd1400getreg(portp, MSVR1);
3042 if (mcor1 & MSVR1_DCD)
3043 portp->sigs |= TIOCM_CD;
3044 else
3045 portp->sigs &= ~TIOCM_CD;
3046 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3047 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003048 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049}
3050
3051/*****************************************************************************/
3052
3053/*
3054 * Set the state of the DTR and RTS signals.
3055 */
3056
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003057static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058{
3059 unsigned char msvr1, msvr2;
3060 unsigned long flags;
3061
Jiri Slabya0564e12006-12-08 02:38:37 -08003062 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3063 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
3065 msvr1 = 0;
3066 msvr2 = 0;
3067 if (dtr > 0)
3068 msvr1 = MSVR1_DTR;
3069 if (rts > 0)
3070 msvr2 = MSVR2_RTS;
3071
Alan Coxb65b5b52006-06-27 02:54:05 -07003072 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 BRDENABLE(portp->brdnr, portp->pagenr);
3074 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3075 if (rts >= 0)
3076 stl_cd1400setreg(portp, MSVR2, msvr2);
3077 if (dtr >= 0)
3078 stl_cd1400setreg(portp, MSVR1, msvr1);
3079 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003080 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081}
3082
3083/*****************************************************************************/
3084
3085/*
3086 * Return the state of the signals.
3087 */
3088
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003089static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090{
3091 unsigned char msvr1, msvr2;
3092 unsigned long flags;
3093 int sigs;
3094
Jiri Slabya0564e12006-12-08 02:38:37 -08003095 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Alan Coxb65b5b52006-06-27 02:54:05 -07003097 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 BRDENABLE(portp->brdnr, portp->pagenr);
3099 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3100 msvr1 = stl_cd1400getreg(portp, MSVR1);
3101 msvr2 = stl_cd1400getreg(portp, MSVR2);
3102 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003103 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
3105 sigs = 0;
3106 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3107 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3108 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3109 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3110#if 0
3111 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3112 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3113#else
3114 sigs |= TIOCM_DSR;
3115#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003116 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117}
3118
3119/*****************************************************************************/
3120
3121/*
3122 * Enable/Disable the Transmitter and/or Receiver.
3123 */
3124
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003125static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126{
3127 unsigned char ccr;
3128 unsigned long flags;
3129
Jiri Slabya0564e12006-12-08 02:38:37 -08003130 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3131
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 ccr = 0;
3133
3134 if (tx == 0)
3135 ccr |= CCR_TXDISABLE;
3136 else if (tx > 0)
3137 ccr |= CCR_TXENABLE;
3138 if (rx == 0)
3139 ccr |= CCR_RXDISABLE;
3140 else if (rx > 0)
3141 ccr |= CCR_RXENABLE;
3142
Alan Coxb65b5b52006-06-27 02:54:05 -07003143 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 BRDENABLE(portp->brdnr, portp->pagenr);
3145 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3146 stl_cd1400ccrwait(portp);
3147 stl_cd1400setreg(portp, CCR, ccr);
3148 stl_cd1400ccrwait(portp);
3149 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003150 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151}
3152
3153/*****************************************************************************/
3154
3155/*
3156 * Start/stop the Transmitter and/or Receiver.
3157 */
3158
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003159static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160{
3161 unsigned char sreron, sreroff;
3162 unsigned long flags;
3163
Jiri Slabya0564e12006-12-08 02:38:37 -08003164 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165
3166 sreron = 0;
3167 sreroff = 0;
3168 if (tx == 0)
3169 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3170 else if (tx == 1)
3171 sreron |= SRER_TXDATA;
3172 else if (tx >= 2)
3173 sreron |= SRER_TXEMPTY;
3174 if (rx == 0)
3175 sreroff |= SRER_RXDATA;
3176 else if (rx > 0)
3177 sreron |= SRER_RXDATA;
3178
Alan Coxb65b5b52006-06-27 02:54:05 -07003179 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 BRDENABLE(portp->brdnr, portp->pagenr);
3181 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3182 stl_cd1400setreg(portp, SRER,
3183 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3184 BRDDISABLE(portp->brdnr);
3185 if (tx > 0)
3186 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003187 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188}
3189
3190/*****************************************************************************/
3191
3192/*
3193 * Disable all interrupts from this port.
3194 */
3195
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003196static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197{
3198 unsigned long flags;
3199
Jiri Slabya0564e12006-12-08 02:38:37 -08003200 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3201
Alan Coxb65b5b52006-06-27 02:54:05 -07003202 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 BRDENABLE(portp->brdnr, portp->pagenr);
3204 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3205 stl_cd1400setreg(portp, SRER, 0);
3206 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003207 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208}
3209
3210/*****************************************************************************/
3211
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003212static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213{
3214 unsigned long flags;
3215
Jiri Slabya0564e12006-12-08 02:38:37 -08003216 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
Alan Coxb65b5b52006-06-27 02:54:05 -07003218 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 BRDENABLE(portp->brdnr, portp->pagenr);
3220 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3221 stl_cd1400setreg(portp, SRER,
3222 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3223 SRER_TXEMPTY));
3224 BRDDISABLE(portp->brdnr);
3225 portp->brklen = len;
3226 if (len == 1)
3227 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003228 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229}
3230
3231/*****************************************************************************/
3232
3233/*
3234 * Take flow control actions...
3235 */
3236
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003237static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238{
3239 struct tty_struct *tty;
3240 unsigned long flags;
3241
Jiri Slabya0564e12006-12-08 02:38:37 -08003242 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Jiri Slaby615e4a72006-12-08 02:38:38 -08003244 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003246 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003247 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 return;
3249
Alan Coxb65b5b52006-06-27 02:54:05 -07003250 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 BRDENABLE(portp->brdnr, portp->pagenr);
3252 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3253
3254 if (state) {
3255 if (tty->termios->c_iflag & IXOFF) {
3256 stl_cd1400ccrwait(portp);
3257 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3258 portp->stats.rxxon++;
3259 stl_cd1400ccrwait(portp);
3260 }
3261/*
3262 * Question: should we return RTS to what it was before? It may
3263 * have been set by an ioctl... Suppose not, since if you have
3264 * hardware flow control set then it is pretty silly to go and
3265 * set the RTS line by hand.
3266 */
3267 if (tty->termios->c_cflag & CRTSCTS) {
3268 stl_cd1400setreg(portp, MCOR1,
3269 (stl_cd1400getreg(portp, MCOR1) |
3270 FIFO_RTSTHRESHOLD));
3271 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3272 portp->stats.rxrtson++;
3273 }
3274 } else {
3275 if (tty->termios->c_iflag & IXOFF) {
3276 stl_cd1400ccrwait(portp);
3277 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3278 portp->stats.rxxoff++;
3279 stl_cd1400ccrwait(portp);
3280 }
3281 if (tty->termios->c_cflag & CRTSCTS) {
3282 stl_cd1400setreg(portp, MCOR1,
3283 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3284 stl_cd1400setreg(portp, MSVR2, 0);
3285 portp->stats.rxrtsoff++;
3286 }
3287 }
3288
3289 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003290 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291}
3292
3293/*****************************************************************************/
3294
3295/*
3296 * Send a flow control character...
3297 */
3298
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003299static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300{
3301 struct tty_struct *tty;
3302 unsigned long flags;
3303
Jiri Slabya0564e12006-12-08 02:38:37 -08003304 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Jiri Slaby615e4a72006-12-08 02:38:38 -08003306 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003308 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003309 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 return;
3311
Alan Coxb65b5b52006-06-27 02:54:05 -07003312 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 BRDENABLE(portp->brdnr, portp->pagenr);
3314 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3315 if (state) {
3316 stl_cd1400ccrwait(portp);
3317 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3318 portp->stats.rxxon++;
3319 stl_cd1400ccrwait(portp);
3320 } else {
3321 stl_cd1400ccrwait(portp);
3322 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3323 portp->stats.rxxoff++;
3324 stl_cd1400ccrwait(portp);
3325 }
3326 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003327 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328}
3329
3330/*****************************************************************************/
3331
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003332static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333{
3334 unsigned long flags;
3335
Jiri Slabya0564e12006-12-08 02:38:37 -08003336 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337
Jiri Slaby615e4a72006-12-08 02:38:38 -08003338 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 return;
3340
Alan Coxb65b5b52006-06-27 02:54:05 -07003341 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 BRDENABLE(portp->brdnr, portp->pagenr);
3343 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3344 stl_cd1400ccrwait(portp);
3345 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3346 stl_cd1400ccrwait(portp);
3347 portp->tx.tail = portp->tx.head;
3348 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003349 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350}
3351
3352/*****************************************************************************/
3353
3354/*
3355 * Return the current state of data flow on this port. This is only
3356 * really interresting when determining if data has fully completed
3357 * transmission or not... This is easy for the cd1400, it accurately
3358 * maintains the busy port flag.
3359 */
3360
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003361static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362{
Jiri Slabya0564e12006-12-08 02:38:37 -08003363 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Jiri Slaby615e4a72006-12-08 02:38:38 -08003365 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003366 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367
Jesper Juhl014c2542006-01-15 02:37:08 +01003368 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369}
3370
3371/*****************************************************************************/
3372
3373/*
3374 * Interrupt service routine for cd1400 EasyIO boards.
3375 */
3376
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003377static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378{
3379 unsigned char svrtype;
3380
Jiri Slabya0564e12006-12-08 02:38:37 -08003381 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382
Alan Coxb65b5b52006-06-27 02:54:05 -07003383 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384 outb(SVRR, iobase);
3385 svrtype = inb(iobase + EREG_DATA);
3386 if (panelp->nrports > 4) {
3387 outb((SVRR + 0x80), iobase);
3388 svrtype |= inb(iobase + EREG_DATA);
3389 }
3390
3391 if (svrtype & SVRR_RX)
3392 stl_cd1400rxisr(panelp, iobase);
3393 else if (svrtype & SVRR_TX)
3394 stl_cd1400txisr(panelp, iobase);
3395 else if (svrtype & SVRR_MDM)
3396 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003397
3398 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399}
3400
3401/*****************************************************************************/
3402
3403/*
3404 * Interrupt service routine for cd1400 panels.
3405 */
3406
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003407static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408{
3409 unsigned char svrtype;
3410
Jiri Slabya0564e12006-12-08 02:38:37 -08003411 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
3413 outb(SVRR, iobase);
3414 svrtype = inb(iobase + EREG_DATA);
3415 outb((SVRR + 0x80), iobase);
3416 svrtype |= inb(iobase + EREG_DATA);
3417 if (svrtype & SVRR_RX)
3418 stl_cd1400rxisr(panelp, iobase);
3419 else if (svrtype & SVRR_TX)
3420 stl_cd1400txisr(panelp, iobase);
3421 else if (svrtype & SVRR_MDM)
3422 stl_cd1400mdmisr(panelp, iobase);
3423}
3424
3425
3426/*****************************************************************************/
3427
3428/*
3429 * Unfortunately we need to handle breaks in the TX data stream, since
3430 * this is the only way to generate them on the cd1400.
3431 */
3432
Jiri Slaby60be4812006-12-08 02:38:40 -08003433static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434{
3435 if (portp->brklen == 1) {
3436 outb((COR2 + portp->uartaddr), ioaddr);
3437 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3438 (ioaddr + EREG_DATA));
3439 outb((TDR + portp->uartaddr), ioaddr);
3440 outb(ETC_CMD, (ioaddr + EREG_DATA));
3441 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3442 outb((SRER + portp->uartaddr), ioaddr);
3443 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3444 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003445 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 } else if (portp->brklen > 1) {
3447 outb((TDR + portp->uartaddr), ioaddr);
3448 outb(ETC_CMD, (ioaddr + EREG_DATA));
3449 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3450 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003451 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 } else {
3453 outb((COR2 + portp->uartaddr), ioaddr);
3454 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3455 (ioaddr + EREG_DATA));
3456 portp->brklen = 0;
3457 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003458 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459}
3460
3461/*****************************************************************************/
3462
3463/*
3464 * Transmit interrupt handler. This has gotta be fast! Handling TX
3465 * chars is pretty simple, stuff as many as possible from the TX buffer
3466 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3467 * are embedded as commands in the data stream. Oh no, had to use a goto!
3468 * This could be optimized more, will do when I get time...
3469 * In practice it is possible that interrupts are enabled but that the
3470 * port has been hung up. Need to handle not having any TX buffer here,
3471 * this is done by using the side effect that head and tail will also
3472 * be NULL if the buffer has been freed.
3473 */
3474
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003475static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003477 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 int len, stlen;
3479 char *head, *tail;
3480 unsigned char ioack, srer;
3481
Jiri Slabya0564e12006-12-08 02:38:37 -08003482 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
3484 ioack = inb(ioaddr + EREG_TXACK);
3485 if (((ioack & panelp->ackmask) != 0) ||
3486 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3487 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3488 return;
3489 }
3490 portp = panelp->ports[(ioack >> 3)];
3491
3492/*
3493 * Unfortunately we need to handle breaks in the data stream, since
3494 * this is the only way to generate them on the cd1400. Do it now if
3495 * a break is to be sent.
3496 */
3497 if (portp->brklen != 0)
3498 if (stl_cd1400breakisr(portp, ioaddr))
3499 goto stl_txalldone;
3500
3501 head = portp->tx.head;
3502 tail = portp->tx.tail;
3503 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3504 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3505 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3506 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01003507 if (portp->port.tty)
3508 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 }
3510
3511 if (len == 0) {
3512 outb((SRER + portp->uartaddr), ioaddr);
3513 srer = inb(ioaddr + EREG_DATA);
3514 if (srer & SRER_TXDATA) {
3515 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3516 } else {
3517 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3518 clear_bit(ASYI_TXBUSY, &portp->istate);
3519 }
3520 outb(srer, (ioaddr + EREG_DATA));
3521 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003522 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003524 stlen = min_t(unsigned int, len,
3525 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 outb((TDR + portp->uartaddr), ioaddr);
3527 outsb((ioaddr + EREG_DATA), tail, stlen);
3528 len -= stlen;
3529 tail += stlen;
3530 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3531 tail = portp->tx.buf;
3532 if (len > 0) {
3533 outsb((ioaddr + EREG_DATA), tail, len);
3534 tail += len;
3535 }
3536 portp->tx.tail = tail;
3537 }
3538
3539stl_txalldone:
3540 outb((EOSRR + portp->uartaddr), ioaddr);
3541 outb(0, (ioaddr + EREG_DATA));
3542}
3543
3544/*****************************************************************************/
3545
3546/*
3547 * Receive character interrupt handler. Determine if we have good chars
3548 * or bad chars and then process appropriately. Good chars are easy
3549 * just shove the lot into the RX buffer and set all status byte to 0.
3550 * If a bad RX char then process as required. This routine needs to be
3551 * fast! In practice it is possible that we get an interrupt on a port
3552 * that is closed. This can happen on hangups - since they completely
3553 * shutdown a port not in user context. Need to handle this case.
3554 */
3555
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003556static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003558 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559 struct tty_struct *tty;
3560 unsigned int ioack, len, buflen;
3561 unsigned char status;
3562 char ch;
3563
Jiri Slabya0564e12006-12-08 02:38:37 -08003564 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
3566 ioack = inb(ioaddr + EREG_RXACK);
3567 if ((ioack & panelp->ackmask) != 0) {
3568 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3569 return;
3570 }
3571 portp = panelp->ports[(ioack >> 3)];
Alan Coxf8ae4762008-07-16 21:56:37 +01003572 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573
3574 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3575 outb((RDCR + portp->uartaddr), ioaddr);
3576 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003577 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003578 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 outb((RDSR + portp->uartaddr), ioaddr);
3580 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3581 portp->stats.rxlost += len;
3582 portp->stats.rxtotal += len;
3583 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003584 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003586 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003588 tty_prepare_flip_string(tty, &ptr, len);
3589 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590 tty_schedule_flip(tty);
3591 portp->stats.rxtotal += len;
3592 }
3593 }
3594 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3595 outb((RDSR + portp->uartaddr), ioaddr);
3596 status = inb(ioaddr + EREG_DATA);
3597 ch = inb(ioaddr + EREG_DATA);
3598 if (status & ST_PARITY)
3599 portp->stats.rxparity++;
3600 if (status & ST_FRAMING)
3601 portp->stats.rxframing++;
3602 if (status & ST_OVERRUN)
3603 portp->stats.rxoverrun++;
3604 if (status & ST_BREAK)
3605 portp->stats.rxbreaks++;
3606 if (status & ST_SCHARMASK) {
3607 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3608 portp->stats.txxon++;
3609 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3610 portp->stats.txxoff++;
3611 goto stl_rxalldone;
3612 }
Alan Cox33f0f882006-01-09 20:54:13 -08003613 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 if (portp->rxmarkmsk & status) {
3615 if (status & ST_BREAK) {
3616 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003617 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 do_SAK(tty);
3619 BRDENABLE(portp->brdnr, portp->pagenr);
3620 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003621 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003623 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003625 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003627 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003629 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003631 tty_insert_flip_char(tty, ch, status);
3632 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 }
3634 } else {
3635 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3636 return;
3637 }
3638
3639stl_rxalldone:
3640 outb((EOSRR + portp->uartaddr), ioaddr);
3641 outb(0, (ioaddr + EREG_DATA));
3642}
3643
3644/*****************************************************************************/
3645
3646/*
3647 * Modem interrupt handler. The is called when the modem signal line
3648 * (DCD) has changed state. Leave most of the work to the off-level
3649 * processing routine.
3650 */
3651
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003652static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003654 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 unsigned int ioack;
3656 unsigned char misr;
3657
Jiri Slabya0564e12006-12-08 02:38:37 -08003658 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
3660 ioack = inb(ioaddr + EREG_MDACK);
3661 if (((ioack & panelp->ackmask) != 0) ||
3662 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3663 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3664 return;
3665 }
3666 portp = panelp->ports[(ioack >> 3)];
3667
3668 outb((MISR + portp->uartaddr), ioaddr);
3669 misr = inb(ioaddr + EREG_DATA);
3670 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003671 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672 portp->stats.modem++;
3673 }
3674
3675 outb((EOSRR + portp->uartaddr), ioaddr);
3676 outb(0, (ioaddr + EREG_DATA));
3677}
3678
3679/*****************************************************************************/
3680/* SC26198 HARDWARE FUNCTIONS */
3681/*****************************************************************************/
3682
3683/*
3684 * These functions get/set/update the registers of the sc26198 UARTs.
3685 * Access to the sc26198 registers is via an address/data io port pair.
3686 * (Maybe should make this inline...)
3687 */
3688
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003689static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690{
3691 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003692 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693}
3694
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003695static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696{
3697 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3698 outb(value, (portp->ioaddr + XP_DATA));
3699}
3700
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003701static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702{
3703 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3704 if (inb(portp->ioaddr + XP_DATA) != value) {
3705 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003706 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003708 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709}
3710
3711/*****************************************************************************/
3712
3713/*
3714 * Functions to get and set the sc26198 global registers.
3715 */
3716
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003717static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718{
3719 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003720 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721}
3722
3723#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003724static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725{
3726 outb(regnr, (portp->ioaddr + XP_ADDR));
3727 outb(value, (portp->ioaddr + XP_DATA));
3728}
3729#endif
3730
3731/*****************************************************************************/
3732
3733/*
3734 * Inbitialize the UARTs in a panel. We don't care what sort of board
3735 * these ports are on - since the port io registers are almost
3736 * identical when dealing with ports.
3737 */
3738
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003739static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
3741 int chipmask, i;
3742 int nrchips, ioaddr;
3743
Jiri Slabya0564e12006-12-08 02:38:37 -08003744 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
3746 BRDENABLE(panelp->brdnr, panelp->pagenr);
3747
3748/*
3749 * Check that each chip is present and started up OK.
3750 */
3751 chipmask = 0;
3752 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3753 if (brdp->brdtype == BRD_ECHPCI)
3754 outb(panelp->pagenr, brdp->ioctrl);
3755
Jiri Slabyc62429d2006-12-08 02:39:14 -08003756 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 ioaddr = panelp->iobase + (i * 4);
3758 outb(SCCR, (ioaddr + XP_ADDR));
3759 outb(CR_RESETALL, (ioaddr + XP_DATA));
3760 outb(TSTR, (ioaddr + XP_ADDR));
3761 if (inb(ioaddr + XP_DATA) != 0) {
3762 printk("STALLION: sc26198 not responding, "
3763 "brd=%d panel=%d chip=%d\n",
3764 panelp->brdnr, panelp->panelnr, i);
3765 continue;
3766 }
3767 chipmask |= (0x1 << i);
3768 outb(GCCR, (ioaddr + XP_ADDR));
3769 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3770 outb(WDTRCR, (ioaddr + XP_ADDR));
3771 outb(0xff, (ioaddr + XP_DATA));
3772 }
3773
3774 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003775 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776}
3777
3778/*****************************************************************************/
3779
3780/*
3781 * Initialize hardware specific port registers.
3782 */
3783
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003784static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785{
Jiri Slabya0564e12006-12-08 02:38:37 -08003786 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3787 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788
Jiri Slaby615e4a72006-12-08 02:38:38 -08003789 if ((brdp == NULL) || (panelp == NULL) ||
3790 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 return;
3792
3793 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3794 portp->uartaddr = (portp->portnr & 0x07) << 4;
3795 portp->pagenr = panelp->pagenr;
3796 portp->hwid = 0x1;
3797
3798 BRDENABLE(portp->brdnr, portp->pagenr);
3799 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3800 BRDDISABLE(portp->brdnr);
3801}
3802
3803/*****************************************************************************/
3804
3805/*
3806 * Set up the sc26198 registers for a port based on the termios port
3807 * settings.
3808 */
3809
Alan Cox606d0992006-12-08 02:38:45 -08003810static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003812 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 unsigned long flags;
3814 unsigned int baudrate;
3815 unsigned char mr0, mr1, mr2, clk;
3816 unsigned char imron, imroff, iopr, ipr;
3817
3818 mr0 = 0;
3819 mr1 = 0;
3820 mr2 = 0;
3821 clk = 0;
3822 iopr = 0;
3823 imron = 0;
3824 imroff = 0;
3825
3826 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003827 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 return;
3829
3830/*
3831 * Set up the RX char ignore mask with those RX error types we
3832 * can ignore.
3833 */
3834 portp->rxignoremsk = 0;
3835 if (tiosp->c_iflag & IGNPAR)
3836 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3837 SR_RXOVERRUN);
3838 if (tiosp->c_iflag & IGNBRK)
3839 portp->rxignoremsk |= SR_RXBREAK;
3840
3841 portp->rxmarkmsk = SR_RXOVERRUN;
3842 if (tiosp->c_iflag & (INPCK | PARMRK))
3843 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3844 if (tiosp->c_iflag & BRKINT)
3845 portp->rxmarkmsk |= SR_RXBREAK;
3846
3847/*
3848 * Go through the char size, parity and stop bits and set all the
3849 * option register appropriately.
3850 */
3851 switch (tiosp->c_cflag & CSIZE) {
3852 case CS5:
3853 mr1 |= MR1_CS5;
3854 break;
3855 case CS6:
3856 mr1 |= MR1_CS6;
3857 break;
3858 case CS7:
3859 mr1 |= MR1_CS7;
3860 break;
3861 default:
3862 mr1 |= MR1_CS8;
3863 break;
3864 }
3865
3866 if (tiosp->c_cflag & CSTOPB)
3867 mr2 |= MR2_STOP2;
3868 else
3869 mr2 |= MR2_STOP1;
3870
3871 if (tiosp->c_cflag & PARENB) {
3872 if (tiosp->c_cflag & PARODD)
3873 mr1 |= (MR1_PARENB | MR1_PARODD);
3874 else
3875 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003876 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
3879 mr1 |= MR1_ERRBLOCK;
3880
3881/*
3882 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3883 * space for hardware flow control and the like. This should be set to
3884 * VMIN.
3885 */
3886 mr2 |= MR2_RXFIFOHALF;
3887
3888/*
3889 * Calculate the baud rate timers. For now we will just assume that
3890 * the input and output baud are the same. The sc26198 has a fixed
3891 * baud rate table, so only discrete baud rates possible.
3892 */
3893 baudrate = tiosp->c_cflag & CBAUD;
3894 if (baudrate & CBAUDEX) {
3895 baudrate &= ~CBAUDEX;
3896 if ((baudrate < 1) || (baudrate > 4))
3897 tiosp->c_cflag &= ~CBAUDEX;
3898 else
3899 baudrate += 15;
3900 }
3901 baudrate = stl_baudrates[baudrate];
3902 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003903 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003905 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003907 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003909 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003911 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 baudrate = (portp->baud_base / portp->custom_divisor);
3913 }
3914 if (baudrate > STL_SC26198MAXBAUD)
3915 baudrate = STL_SC26198MAXBAUD;
3916
Jiri Slabyc62429d2006-12-08 02:39:14 -08003917 if (baudrate > 0)
3918 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 if (baudrate <= sc26198_baudtable[clk])
3920 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
3922/*
3923 * Check what form of modem signaling is required and set it up.
3924 */
3925 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003926 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 } else {
3928 iopr |= IOPR_DCDCOS;
3929 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003930 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 }
3932
3933/*
3934 * Setup sc26198 enhanced modes if we can. In particular we want to
3935 * handle as much of the flow control as possible automatically. As
3936 * well as saving a few CPU cycles it will also greatly improve flow
3937 * control reliability.
3938 */
3939 if (tiosp->c_iflag & IXON) {
3940 mr0 |= MR0_SWFTX | MR0_SWFT;
3941 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003942 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003944
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 if (tiosp->c_iflag & IXOFF)
3946 mr0 |= MR0_SWFRX;
3947
3948 if (tiosp->c_cflag & CRTSCTS) {
3949 mr2 |= MR2_AUTOCTS;
3950 mr1 |= MR1_AUTORTS;
3951 }
3952
3953/*
3954 * All sc26198 register values calculated so go through and set
3955 * them all up.
3956 */
3957
Jiri Slabya0564e12006-12-08 02:38:37 -08003958 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003960 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3961 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3962 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3964 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965
Alan Coxb65b5b52006-06-27 02:54:05 -07003966 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967 BRDENABLE(portp->brdnr, portp->pagenr);
3968 stl_sc26198setreg(portp, IMR, 0);
3969 stl_sc26198updatereg(portp, MR0, mr0);
3970 stl_sc26198updatereg(portp, MR1, mr1);
3971 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3972 stl_sc26198updatereg(portp, MR2, mr2);
3973 stl_sc26198updatereg(portp, IOPIOR,
3974 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3975
3976 if (baudrate > 0) {
3977 stl_sc26198setreg(portp, TXCSR, clk);
3978 stl_sc26198setreg(portp, RXCSR, clk);
3979 }
3980
3981 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3982 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3983
3984 ipr = stl_sc26198getreg(portp, IPR);
3985 if (ipr & IPR_DCD)
3986 portp->sigs &= ~TIOCM_CD;
3987 else
3988 portp->sigs |= TIOCM_CD;
3989
3990 portp->imr = (portp->imr & ~imroff) | imron;
3991 stl_sc26198setreg(portp, IMR, portp->imr);
3992 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003993 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994}
3995
3996/*****************************************************************************/
3997
3998/*
3999 * Set the state of the DTR and RTS signals.
4000 */
4001
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004002static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003{
4004 unsigned char iopioron, iopioroff;
4005 unsigned long flags;
4006
Jiri Slabya0564e12006-12-08 02:38:37 -08004007 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4008 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
4010 iopioron = 0;
4011 iopioroff = 0;
4012 if (dtr == 0)
4013 iopioroff |= IPR_DTR;
4014 else if (dtr > 0)
4015 iopioron |= IPR_DTR;
4016 if (rts == 0)
4017 iopioroff |= IPR_RTS;
4018 else if (rts > 0)
4019 iopioron |= IPR_RTS;
4020
Alan Coxb65b5b52006-06-27 02:54:05 -07004021 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 BRDENABLE(portp->brdnr, portp->pagenr);
4023 stl_sc26198setreg(portp, IOPIOR,
4024 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4025 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004026 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027}
4028
4029/*****************************************************************************/
4030
4031/*
4032 * Return the state of the signals.
4033 */
4034
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004035static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036{
4037 unsigned char ipr;
4038 unsigned long flags;
4039 int sigs;
4040
Jiri Slabya0564e12006-12-08 02:38:37 -08004041 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Alan Coxb65b5b52006-06-27 02:54:05 -07004043 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 BRDENABLE(portp->brdnr, portp->pagenr);
4045 ipr = stl_sc26198getreg(portp, IPR);
4046 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004047 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
4049 sigs = 0;
4050 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4051 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4052 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4053 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4054 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004055 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056}
4057
4058/*****************************************************************************/
4059
4060/*
4061 * Enable/Disable the Transmitter and/or Receiver.
4062 */
4063
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004064static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065{
4066 unsigned char ccr;
4067 unsigned long flags;
4068
Jiri Slabya0564e12006-12-08 02:38:37 -08004069 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
4071 ccr = portp->crenable;
4072 if (tx == 0)
4073 ccr &= ~CR_TXENABLE;
4074 else if (tx > 0)
4075 ccr |= CR_TXENABLE;
4076 if (rx == 0)
4077 ccr &= ~CR_RXENABLE;
4078 else if (rx > 0)
4079 ccr |= CR_RXENABLE;
4080
Alan Coxb65b5b52006-06-27 02:54:05 -07004081 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 BRDENABLE(portp->brdnr, portp->pagenr);
4083 stl_sc26198setreg(portp, SCCR, ccr);
4084 BRDDISABLE(portp->brdnr);
4085 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004086 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087}
4088
4089/*****************************************************************************/
4090
4091/*
4092 * Start/stop the Transmitter and/or Receiver.
4093 */
4094
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004095static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096{
4097 unsigned char imr;
4098 unsigned long flags;
4099
Jiri Slabya0564e12006-12-08 02:38:37 -08004100 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
4102 imr = portp->imr;
4103 if (tx == 0)
4104 imr &= ~IR_TXRDY;
4105 else if (tx == 1)
4106 imr |= IR_TXRDY;
4107 if (rx == 0)
4108 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4109 else if (rx > 0)
4110 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4111
Alan Coxb65b5b52006-06-27 02:54:05 -07004112 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 BRDENABLE(portp->brdnr, portp->pagenr);
4114 stl_sc26198setreg(portp, IMR, imr);
4115 BRDDISABLE(portp->brdnr);
4116 portp->imr = imr;
4117 if (tx > 0)
4118 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004119 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120}
4121
4122/*****************************************************************************/
4123
4124/*
4125 * Disable all interrupts from this port.
4126 */
4127
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004128static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129{
4130 unsigned long flags;
4131
Jiri Slabya0564e12006-12-08 02:38:37 -08004132 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
Alan Coxb65b5b52006-06-27 02:54:05 -07004134 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 BRDENABLE(portp->brdnr, portp->pagenr);
4136 portp->imr = 0;
4137 stl_sc26198setreg(portp, IMR, 0);
4138 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004139 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140}
4141
4142/*****************************************************************************/
4143
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004144static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145{
4146 unsigned long flags;
4147
Jiri Slabya0564e12006-12-08 02:38:37 -08004148 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
Alan Coxb65b5b52006-06-27 02:54:05 -07004150 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 BRDENABLE(portp->brdnr, portp->pagenr);
4152 if (len == 1) {
4153 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4154 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004155 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004157
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004159 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160}
4161
4162/*****************************************************************************/
4163
4164/*
4165 * Take flow control actions...
4166 */
4167
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004168static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
4170 struct tty_struct *tty;
4171 unsigned long flags;
4172 unsigned char mr0;
4173
Jiri Slabya0564e12006-12-08 02:38:37 -08004174 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175
Jiri Slaby615e4a72006-12-08 02:38:38 -08004176 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004178 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004179 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 return;
4181
Alan Coxb65b5b52006-06-27 02:54:05 -07004182 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 BRDENABLE(portp->brdnr, portp->pagenr);
4184
4185 if (state) {
4186 if (tty->termios->c_iflag & IXOFF) {
4187 mr0 = stl_sc26198getreg(portp, MR0);
4188 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4189 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4190 mr0 |= MR0_SWFRX;
4191 portp->stats.rxxon++;
4192 stl_sc26198wait(portp);
4193 stl_sc26198setreg(portp, MR0, mr0);
4194 }
4195/*
4196 * Question: should we return RTS to what it was before? It may
4197 * have been set by an ioctl... Suppose not, since if you have
4198 * hardware flow control set then it is pretty silly to go and
4199 * set the RTS line by hand.
4200 */
4201 if (tty->termios->c_cflag & CRTSCTS) {
4202 stl_sc26198setreg(portp, MR1,
4203 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4204 stl_sc26198setreg(portp, IOPIOR,
4205 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4206 portp->stats.rxrtson++;
4207 }
4208 } else {
4209 if (tty->termios->c_iflag & IXOFF) {
4210 mr0 = stl_sc26198getreg(portp, MR0);
4211 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4212 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4213 mr0 &= ~MR0_SWFRX;
4214 portp->stats.rxxoff++;
4215 stl_sc26198wait(portp);
4216 stl_sc26198setreg(portp, MR0, mr0);
4217 }
4218 if (tty->termios->c_cflag & CRTSCTS) {
4219 stl_sc26198setreg(portp, MR1,
4220 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4221 stl_sc26198setreg(portp, IOPIOR,
4222 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4223 portp->stats.rxrtsoff++;
4224 }
4225 }
4226
4227 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004228 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229}
4230
4231/*****************************************************************************/
4232
4233/*
4234 * Send a flow control character.
4235 */
4236
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004237static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238{
4239 struct tty_struct *tty;
4240 unsigned long flags;
4241 unsigned char mr0;
4242
Jiri Slabya0564e12006-12-08 02:38:37 -08004243 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Jiri Slaby615e4a72006-12-08 02:38:38 -08004245 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004247 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004248 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249 return;
4250
Alan Coxb65b5b52006-06-27 02:54:05 -07004251 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 BRDENABLE(portp->brdnr, portp->pagenr);
4253 if (state) {
4254 mr0 = stl_sc26198getreg(portp, MR0);
4255 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4256 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4257 mr0 |= MR0_SWFRX;
4258 portp->stats.rxxon++;
4259 stl_sc26198wait(portp);
4260 stl_sc26198setreg(portp, MR0, mr0);
4261 } else {
4262 mr0 = stl_sc26198getreg(portp, MR0);
4263 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4264 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4265 mr0 &= ~MR0_SWFRX;
4266 portp->stats.rxxoff++;
4267 stl_sc26198wait(portp);
4268 stl_sc26198setreg(portp, MR0, mr0);
4269 }
4270 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004271 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272}
4273
4274/*****************************************************************************/
4275
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004276static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277{
4278 unsigned long flags;
4279
Jiri Slabya0564e12006-12-08 02:38:37 -08004280 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281
Jiri Slaby615e4a72006-12-08 02:38:38 -08004282 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 return;
4284
Alan Coxb65b5b52006-06-27 02:54:05 -07004285 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 BRDENABLE(portp->brdnr, portp->pagenr);
4287 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4288 stl_sc26198setreg(portp, SCCR, portp->crenable);
4289 BRDDISABLE(portp->brdnr);
4290 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004291 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292}
4293
4294/*****************************************************************************/
4295
4296/*
4297 * Return the current state of data flow on this port. This is only
4298 * really interresting when determining if data has fully completed
4299 * transmission or not... The sc26198 interrupt scheme cannot
4300 * determine when all data has actually drained, so we need to
4301 * check the port statusy register to be sure.
4302 */
4303
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004304static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305{
4306 unsigned long flags;
4307 unsigned char sr;
4308
Jiri Slabya0564e12006-12-08 02:38:37 -08004309 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310
Jiri Slaby615e4a72006-12-08 02:38:38 -08004311 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004312 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004314 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315
Alan Coxb65b5b52006-06-27 02:54:05 -07004316 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 BRDENABLE(portp->brdnr, portp->pagenr);
4318 sr = stl_sc26198getreg(portp, SR);
4319 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004320 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Jesper Juhl014c2542006-01-15 02:37:08 +01004322 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325/*****************************************************************************/
4326
4327/*
4328 * Delay for a small amount of time, to give the sc26198 a chance
4329 * to process a command...
4330 */
4331
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004332static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333{
4334 int i;
4335
Jiri Slabya0564e12006-12-08 02:38:37 -08004336 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Jiri Slaby615e4a72006-12-08 02:38:38 -08004338 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 return;
4340
Jiri Slabyc62429d2006-12-08 02:39:14 -08004341 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 stl_sc26198getglobreg(portp, TSTR);
4343}
4344
4345/*****************************************************************************/
4346
4347/*
4348 * If we are TX flow controlled and in IXANY mode then we may
4349 * need to unflow control here. We gotta do this because of the
4350 * automatic flow control modes of the sc26198.
4351 */
4352
Jiri Slaby60be4812006-12-08 02:38:40 -08004353static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354{
4355 unsigned char mr0;
4356
4357 mr0 = stl_sc26198getreg(portp, MR0);
4358 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4359 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4360 stl_sc26198wait(portp);
4361 stl_sc26198setreg(portp, MR0, mr0);
4362 clear_bit(ASYI_TXFLOWED, &portp->istate);
4363}
4364
4365/*****************************************************************************/
4366
4367/*
4368 * Interrupt service routine for sc26198 panels.
4369 */
4370
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004371static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004373 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 unsigned int iack;
4375
Alan Coxb65b5b52006-06-27 02:54:05 -07004376 spin_lock(&brd_lock);
4377
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378/*
4379 * Work around bug in sc26198 chip... Cannot have A6 address
4380 * line of UART high, else iack will be returned as 0.
4381 */
4382 outb(0, (iobase + 1));
4383
4384 iack = inb(iobase + XP_IACK);
4385 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4386
4387 if (iack & IVR_RXDATA)
4388 stl_sc26198rxisr(portp, iack);
4389 else if (iack & IVR_TXDATA)
4390 stl_sc26198txisr(portp);
4391 else
4392 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004393
4394 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395}
4396
4397/*****************************************************************************/
4398
4399/*
4400 * Transmit interrupt handler. This has gotta be fast! Handling TX
4401 * chars is pretty simple, stuff as many as possible from the TX buffer
4402 * into the sc26198 FIFO.
4403 * In practice it is possible that interrupts are enabled but that the
4404 * port has been hung up. Need to handle not having any TX buffer here,
4405 * this is done by using the side effect that head and tail will also
4406 * be NULL if the buffer has been freed.
4407 */
4408
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004409static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410{
4411 unsigned int ioaddr;
4412 unsigned char mr0;
4413 int len, stlen;
4414 char *head, *tail;
4415
Jiri Slabya0564e12006-12-08 02:38:37 -08004416 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
4418 ioaddr = portp->ioaddr;
4419 head = portp->tx.head;
4420 tail = portp->tx.tail;
4421 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4422 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4423 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4424 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01004425 if (portp->port.tty)
4426 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 }
4428
4429 if (len == 0) {
4430 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4431 mr0 = inb(ioaddr + XP_DATA);
4432 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4433 portp->imr &= ~IR_TXRDY;
4434 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4435 outb(portp->imr, (ioaddr + XP_DATA));
4436 clear_bit(ASYI_TXBUSY, &portp->istate);
4437 } else {
4438 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4439 outb(mr0, (ioaddr + XP_DATA));
4440 }
4441 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004442 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004444 stlen = min_t(unsigned int, len,
4445 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446 outb(GTXFIFO, (ioaddr + XP_ADDR));
4447 outsb((ioaddr + XP_DATA), tail, stlen);
4448 len -= stlen;
4449 tail += stlen;
4450 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4451 tail = portp->tx.buf;
4452 if (len > 0) {
4453 outsb((ioaddr + XP_DATA), tail, len);
4454 tail += len;
4455 }
4456 portp->tx.tail = tail;
4457 }
4458}
4459
4460/*****************************************************************************/
4461
4462/*
4463 * Receive character interrupt handler. Determine if we have good chars
4464 * or bad chars and then process appropriately. Good chars are easy
4465 * just shove the lot into the RX buffer and set all status byte to 0.
4466 * If a bad RX char then process as required. This routine needs to be
4467 * fast! In practice it is possible that we get an interrupt on a port
4468 * that is closed. This can happen on hangups - since they completely
4469 * shutdown a port not in user context. Need to handle this case.
4470 */
4471
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004472static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473{
4474 struct tty_struct *tty;
4475 unsigned int len, buflen, ioaddr;
4476
Jiri Slabya0564e12006-12-08 02:38:37 -08004477 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
Alan Coxf8ae4762008-07-16 21:56:37 +01004479 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 ioaddr = portp->ioaddr;
4481 outb(GIBCR, (ioaddr + XP_ADDR));
4482 len = inb(ioaddr + XP_DATA) + 1;
4483
4484 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004485 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004486 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487 outb(GRXFIFO, (ioaddr + XP_ADDR));
4488 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4489 portp->stats.rxlost += len;
4490 portp->stats.rxtotal += len;
4491 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004492 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004494 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004496 tty_prepare_flip_string(tty, &ptr, len);
4497 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498 tty_schedule_flip(tty);
4499 portp->stats.rxtotal += len;
4500 }
4501 }
4502 } else {
4503 stl_sc26198rxbadchars(portp);
4504 }
4505
4506/*
4507 * If we are TX flow controlled and in IXANY mode then we may need
4508 * to unflow control here. We gotta do this because of the automatic
4509 * flow control modes of the sc26198.
4510 */
4511 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004512 if ((tty != NULL) &&
4513 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 (tty->termios->c_iflag & IXANY)) {
4515 stl_sc26198txunflow(portp, tty);
4516 }
4517 }
4518}
4519
4520/*****************************************************************************/
4521
4522/*
4523 * Process an RX bad character.
4524 */
4525
Jiri Slaby60be4812006-12-08 02:38:40 -08004526static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527{
4528 struct tty_struct *tty;
4529 unsigned int ioaddr;
4530
Alan Coxf8ae4762008-07-16 21:56:37 +01004531 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 ioaddr = portp->ioaddr;
4533
4534 if (status & SR_RXPARITY)
4535 portp->stats.rxparity++;
4536 if (status & SR_RXFRAMING)
4537 portp->stats.rxframing++;
4538 if (status & SR_RXOVERRUN)
4539 portp->stats.rxoverrun++;
4540 if (status & SR_RXBREAK)
4541 portp->stats.rxbreaks++;
4542
Jiri Slaby615e4a72006-12-08 02:38:38 -08004543 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 ((portp->rxignoremsk & status) == 0)) {
4545 if (portp->rxmarkmsk & status) {
4546 if (status & SR_RXBREAK) {
4547 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004548 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549 do_SAK(tty);
4550 BRDENABLE(portp->brdnr, portp->pagenr);
4551 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004552 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004554 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004556 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004558 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004560 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562
Alan Cox33f0f882006-01-09 20:54:13 -08004563 tty_insert_flip_char(tty, ch, status);
4564 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565
4566 if (status == 0)
4567 portp->stats.rxtotal++;
4568 }
4569}
4570
4571/*****************************************************************************/
4572
4573/*
4574 * Process all characters in the RX FIFO of the UART. Check all char
4575 * status bytes as well, and process as required. We need to check
4576 * all bytes in the FIFO, in case some more enter the FIFO while we
4577 * are here. To get the exact character error type we need to switch
4578 * into CHAR error mode (that is why we need to make sure we empty
4579 * the FIFO).
4580 */
4581
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004582static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583{
4584 unsigned char status, mr1;
4585 char ch;
4586
4587/*
4588 * To get the precise error type for each character we must switch
4589 * back into CHAR error mode.
4590 */
4591 mr1 = stl_sc26198getreg(portp, MR1);
4592 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4593
4594 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4595 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4596 ch = stl_sc26198getreg(portp, RXFIFO);
4597 stl_sc26198rxbadch(portp, status, ch);
4598 }
4599
4600/*
4601 * To get correct interrupt class we must switch back into BLOCK
4602 * error mode.
4603 */
4604 stl_sc26198setreg(portp, MR1, mr1);
4605}
4606
4607/*****************************************************************************/
4608
4609/*
4610 * Other interrupt handler. This includes modem signals, flow
4611 * control actions, etc. Most stuff is left to off-level interrupt
4612 * processing time.
4613 */
4614
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004615static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616{
4617 unsigned char cir, ipr, xisr;
4618
Jiri Slabya0564e12006-12-08 02:38:37 -08004619 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620
4621 cir = stl_sc26198getglobreg(portp, CIR);
4622
4623 switch (cir & CIR_SUBTYPEMASK) {
4624 case CIR_SUBCOS:
4625 ipr = stl_sc26198getreg(portp, IPR);
4626 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004627 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 portp->stats.modem++;
4629 }
4630 break;
4631 case CIR_SUBXONXOFF:
4632 xisr = stl_sc26198getreg(portp, XISR);
4633 if (xisr & XISR_RXXONGOT) {
4634 set_bit(ASYI_TXFLOWED, &portp->istate);
4635 portp->stats.txxoff++;
4636 }
4637 if (xisr & XISR_RXXOFFGOT) {
4638 clear_bit(ASYI_TXFLOWED, &portp->istate);
4639 portp->stats.txxon++;
4640 }
4641 break;
4642 case CIR_SUBBREAK:
4643 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4644 stl_sc26198rxbadchars(portp);
4645 break;
4646 default:
4647 break;
4648 }
4649}
4650
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004651static void stl_free_isabrds(void)
4652{
4653 struct stlbrd *brdp;
4654 unsigned int i;
4655
4656 for (i = 0; i < stl_nrbrds; i++) {
4657 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4658 continue;
4659
4660 free_irq(brdp->irq, brdp);
4661
4662 stl_cleanup_panels(brdp);
4663
4664 release_region(brdp->ioaddr1, brdp->iosize1);
4665 if (brdp->iosize2 > 0)
4666 release_region(brdp->ioaddr2, brdp->iosize2);
4667
4668 kfree(brdp);
4669 stl_brds[i] = NULL;
4670 }
4671}
4672
Jiri Slaby23b85a12006-12-08 02:38:40 -08004673/*
4674 * Loadable module initialization stuff.
4675 */
4676static int __init stallion_module_init(void)
4677{
Jiri Slaby843b5682006-12-08 02:39:12 -08004678 struct stlbrd *brdp;
4679 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004680 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004681 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004682
4683 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4684
4685 spin_lock_init(&stallion_lock);
4686 spin_lock_init(&brd_lock);
4687
Jiri Slabye4151092007-06-08 13:46:52 -07004688 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4689 if (!stl_serial) {
4690 retval = -ENOMEM;
4691 goto err;
4692 }
4693
4694 stl_serial->owner = THIS_MODULE;
4695 stl_serial->driver_name = stl_drvname;
4696 stl_serial->name = "ttyE";
4697 stl_serial->major = STL_SERIALMAJOR;
4698 stl_serial->minor_start = 0;
4699 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4700 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4701 stl_serial->init_termios = stl_deftermios;
4702 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4703 tty_set_operations(stl_serial, &stl_ops);
4704
4705 retval = tty_register_driver(stl_serial);
4706 if (retval) {
4707 printk("STALLION: failed to register serial driver\n");
4708 goto err_frtty;
4709 }
4710
Jiri Slaby843b5682006-12-08 02:39:12 -08004711/*
4712 * Find any dynamically supported boards. That is via module load
4713 * line options.
4714 */
4715 for (i = stl_nrbrds; i < stl_nargs; i++) {
4716 memset(&conf, 0, sizeof(conf));
4717 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4718 continue;
4719 if ((brdp = stl_allocbrd()) == NULL)
4720 continue;
4721 brdp->brdnr = i;
4722 brdp->brdtype = conf.brdtype;
4723 brdp->ioaddr1 = conf.ioaddr1;
4724 brdp->ioaddr2 = conf.ioaddr2;
4725 brdp->irq = conf.irq;
4726 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004727 stl_brds[brdp->brdnr] = brdp;
4728 if (stl_brdinit(brdp)) {
4729 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004730 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004731 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004732 for (j = 0; j < brdp->nrports; j++)
4733 tty_register_device(stl_serial,
4734 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004735 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004736 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004737 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004738
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004739 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004740 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004741 if (retval && stl_nrbrds == 0) {
4742 printk(KERN_ERR "STALLION: can't register pci driver\n");
4743 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004744 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004745
4746/*
4747 * Set up a character driver for per board stuff. This is mainly used
4748 * to do stats ioctls on the ports.
4749 */
4750 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4751 printk("STALLION: failed to register serial board device\n");
4752
4753 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004754 if (IS_ERR(stallion_class))
4755 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004756 for (i = 0; i < 4; i++)
Greg Kroah-Hartman47aa5792008-05-21 12:52:33 -07004757 device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4758 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004759
Jiri Slaby23b85a12006-12-08 02:38:40 -08004760 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004761err_unrtty:
4762 tty_unregister_driver(stl_serial);
4763err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004764 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004765err:
4766 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004767}
4768
4769static void __exit stallion_module_exit(void)
4770{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004771 struct stlbrd *brdp;
4772 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004773
4774 pr_debug("cleanup_module()\n");
4775
4776 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4777 stl_drvversion);
4778
4779/*
4780 * Free up all allocated resources used by the ports. This includes
4781 * memory and interrupts. As part of this process we will also do
4782 * a hangup on every open port - to try to flush out any processes
4783 * hanging onto ports.
4784 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004785 for (i = 0; i < stl_nrbrds; i++) {
4786 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4787 continue;
4788 for (j = 0; j < brdp->nrports; j++)
4789 tty_unregister_device(stl_serial,
4790 brdp->brdnr * STL_MAXPORTS + j);
4791 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004792
Jiri Slaby23b85a12006-12-08 02:38:40 -08004793 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004794 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004795 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004796 class_destroy(stallion_class);
4797
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004798 pci_unregister_driver(&stl_pcidriver);
4799
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004800 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004801
4802 tty_unregister_driver(stl_serial);
4803 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004804}
4805
4806module_init(stallion_module_init);
4807module_exit(stallion_module_exit);
4808
4809MODULE_AUTHOR("Greg Ungerer");
4810MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4811MODULE_LICENSE("GPL");