blob: de5a725c3cc0493ddfcdb19f9074561c584638b4 [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 unsigned int ival;
1260 int rc;
1261 void __user *argp = (void __user *)arg;
1262
Jiri Slabya0564e12006-12-08 02:38:37 -08001263 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1264 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
Jiri Slaby615e4a72006-12-08 02:38:38 -08001266 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001267 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001269 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001270 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
1272 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001273 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001275 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 rc = 0;
1278
Alan Coxf433c652008-04-30 00:53:23 -07001279 lock_kernel();
1280
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 case TIOCGSERIAL:
1283 rc = stl_getserial(portp, argp);
1284 break;
1285 case TIOCSSERIAL:
1286 rc = stl_setserial(portp, argp);
1287 break;
1288 case COM_GETPORTSTATS:
1289 rc = stl_getportstats(portp, argp);
1290 break;
1291 case COM_CLRPORTSTATS:
1292 rc = stl_clrportstats(portp, argp);
1293 break;
1294 case TIOCSERCONFIG:
1295 case TIOCSERGWILD:
1296 case TIOCSERSWILD:
1297 case TIOCSERGETLSR:
1298 case TIOCSERGSTRUCT:
1299 case TIOCSERGETMULTI:
1300 case TIOCSERSETMULTI:
1301 default:
1302 rc = -ENOIOCTLCMD;
1303 break;
1304 }
Alan Coxf433c652008-04-30 00:53:23 -07001305 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001306 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307}
1308
1309/*****************************************************************************/
1310
Jiri Slaby96b066b2006-12-08 02:38:42 -08001311/*
1312 * Start the transmitter again. Just turn TX interrupts back on.
1313 */
1314
1315static void stl_start(struct tty_struct *tty)
1316{
1317 struct stlport *portp;
1318
1319 pr_debug("stl_start(tty=%p)\n", tty);
1320
1321 if (tty == NULL)
1322 return;
1323 portp = tty->driver_data;
1324 if (portp == NULL)
1325 return;
1326 stl_startrxtx(portp, -1, 1);
1327}
1328
1329/*****************************************************************************/
1330
Alan Cox606d0992006-12-08 02:38:45 -08001331static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001333 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001334 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Jiri Slabya0564e12006-12-08 02:38:37 -08001336 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Jiri Slaby615e4a72006-12-08 02:38:38 -08001338 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return;
1340 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001341 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 return;
1343
1344 tiosp = tty->termios;
1345 if ((tiosp->c_cflag == old->c_cflag) &&
1346 (tiosp->c_iflag == old->c_iflag))
1347 return;
1348
1349 stl_setport(portp, tiosp);
1350 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1351 -1);
1352 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1353 tty->hw_stopped = 0;
1354 stl_start(tty);
1355 }
1356 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001357 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358}
1359
1360/*****************************************************************************/
1361
1362/*
1363 * Attempt to flow control who ever is sending us data. Based on termios
1364 * settings use software or/and hardware flow control.
1365 */
1366
1367static void stl_throttle(struct tty_struct *tty)
1368{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001369 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Jiri Slabya0564e12006-12-08 02:38:37 -08001371 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Jiri Slaby615e4a72006-12-08 02:38:38 -08001373 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return;
1375 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001376 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 return;
1378 stl_flowctrl(portp, 0);
1379}
1380
1381/*****************************************************************************/
1382
1383/*
1384 * Unflow control the device sending us data...
1385 */
1386
1387static void stl_unthrottle(struct tty_struct *tty)
1388{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001389 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Jiri Slabya0564e12006-12-08 02:38:37 -08001391 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Jiri Slaby615e4a72006-12-08 02:38:38 -08001393 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return;
1395 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001396 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return;
1398 stl_flowctrl(portp, 1);
1399}
1400
1401/*****************************************************************************/
1402
1403/*
1404 * Stop the transmitter. Basically to do this we will just turn TX
1405 * interrupts off.
1406 */
1407
1408static void stl_stop(struct tty_struct *tty)
1409{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001410 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Jiri Slabya0564e12006-12-08 02:38:37 -08001412 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return;
1416 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001417 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 return;
1419 stl_startrxtx(portp, -1, 0);
1420}
1421
1422/*****************************************************************************/
1423
1424/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 * Hangup this port. This is pretty much like closing the port, only
1426 * a little more brutal. No waiting for data to drain. Shutdown the
1427 * port and maybe drop signals.
1428 */
1429
1430static void stl_hangup(struct tty_struct *tty)
1431{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001432 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Jiri Slabya0564e12006-12-08 02:38:37 -08001434 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Jiri Slaby615e4a72006-12-08 02:38:38 -08001436 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return;
1438 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001439 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 return;
1441
Alan Coxf8ae4762008-07-16 21:56:37 +01001442 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 stl_disableintrs(portp);
1444 if (tty->termios->c_cflag & HUPCL)
1445 stl_setsignals(portp, 0, 0);
1446 stl_enablerxtx(portp, 0, 0);
1447 stl_flushbuffer(tty);
1448 portp->istate = 0;
1449 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001450 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001452 portp->tx.buf = NULL;
1453 portp->tx.head = NULL;
1454 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 }
Alan Coxf8ae4762008-07-16 21:56:37 +01001456 portp->port.tty = NULL;
1457 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1458 portp->port.count = 0;
1459 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460}
1461
1462/*****************************************************************************/
1463
David Howells4a561222008-07-22 11:18:43 +01001464static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001466 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Jiri Slabya0564e12006-12-08 02:38:37 -08001468 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Jiri Slaby615e4a72006-12-08 02:38:38 -08001470 if (tty == NULL)
David Howells4a561222008-07-22 11:18:43 +01001471 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001473 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001474 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001477 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478}
1479
1480/*****************************************************************************/
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482static void stl_sendxchar(struct tty_struct *tty, char ch)
1483{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001484 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Jiri Slabya0564e12006-12-08 02:38:37 -08001486 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jiri Slaby615e4a72006-12-08 02:38:38 -08001488 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return;
1490 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001491 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 return;
1493
1494 if (ch == STOP_CHAR(tty))
1495 stl_sendflow(portp, 0);
1496 else if (ch == START_CHAR(tty))
1497 stl_sendflow(portp, 1);
1498 else
1499 stl_putchar(tty, ch);
1500}
1501
1502/*****************************************************************************/
1503
1504#define MAXLINE 80
1505
1506/*
1507 * Format info for a specified port. The line is deliberately limited
1508 * to 80 characters. (If it is too long it will be truncated, if too
1509 * short then padded with spaces).
1510 */
1511
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001512static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
1514 char *sp;
1515 int sigs, cnt;
1516
1517 sp = pos;
1518 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1519 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1520 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1521
1522 if (portp->stats.rxframing)
1523 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1524 if (portp->stats.rxparity)
1525 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1526 if (portp->stats.rxbreaks)
1527 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1528 if (portp->stats.rxoverrun)
1529 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1530
1531 sigs = stl_getsignals(portp);
1532 cnt = sprintf(sp, "%s%s%s%s%s ",
1533 (sigs & TIOCM_RTS) ? "|RTS" : "",
1534 (sigs & TIOCM_CTS) ? "|CTS" : "",
1535 (sigs & TIOCM_DTR) ? "|DTR" : "",
1536 (sigs & TIOCM_CD) ? "|DCD" : "",
1537 (sigs & TIOCM_DSR) ? "|DSR" : "");
1538 *sp = ' ';
1539 sp += cnt;
1540
Jiri Slabyc62429d2006-12-08 02:39:14 -08001541 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 *sp++ = ' ';
1543 if (cnt >= MAXLINE)
1544 pos[(MAXLINE - 2)] = '+';
1545 pos[(MAXLINE - 1)] = '\n';
1546
Jesper Juhl014c2542006-01-15 02:37:08 +01001547 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548}
1549
1550/*****************************************************************************/
1551
1552/*
1553 * Port info, read from the /proc file system.
1554 */
1555
1556static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1557{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001558 struct stlbrd *brdp;
1559 struct stlpanel *panelp;
1560 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001561 unsigned int brdnr, panelnr, portnr;
1562 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 char *pos;
1564
Jiri Slabya0564e12006-12-08 02:38:37 -08001565 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1566 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 pos = page;
1569 totalport = 0;
1570 curoff = 0;
1571
1572 if (off == 0) {
1573 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1574 stl_drvversion);
1575 while (pos < (page + MAXLINE - 1))
1576 *pos++ = ' ';
1577 *pos++ = '\n';
1578 }
1579 curoff = MAXLINE;
1580
1581/*
1582 * We scan through for each board, panel and port. The offset is
1583 * calculated on the fly, and irrelevant ports are skipped.
1584 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001585 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001587 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 continue;
1589 if (brdp->state == 0)
1590 continue;
1591
1592 maxoff = curoff + (brdp->nrports * MAXLINE);
1593 if (off >= maxoff) {
1594 curoff = maxoff;
1595 continue;
1596 }
1597
1598 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001599 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001601 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 continue;
1603
1604 maxoff = curoff + (panelp->nrports * MAXLINE);
1605 if (off >= maxoff) {
1606 curoff = maxoff;
1607 totalport += panelp->nrports;
1608 continue;
1609 }
1610
Jiri Slabyc62429d2006-12-08 02:39:14 -08001611 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 totalport++) {
1613 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001614 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 continue;
1616 if (off >= (curoff += MAXLINE))
1617 continue;
1618 if ((pos - page + MAXLINE) > count)
1619 goto stl_readdone;
1620 pos += stl_portinfo(portp, totalport, pos);
1621 }
1622 }
1623 }
1624
1625 *eof = 1;
1626
1627stl_readdone:
1628 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001629 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630}
1631
1632/*****************************************************************************/
1633
1634/*
1635 * All board interrupts are vectored through here first. This code then
1636 * calls off to the approrpriate board interrupt handlers.
1637 */
1638
David Howells7d12e782006-10-05 14:55:46 +01001639static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001641 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
Jeff Garzika6f97b22007-10-31 05:20:49 -04001643 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 return IRQ_RETVAL((* brdp->isr)(brdp));
1646}
1647
1648/*****************************************************************************/
1649
1650/*
1651 * Interrupt service routine for EasyIO board types.
1652 */
1653
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001654static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001656 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 unsigned int iobase;
1658 int handled = 0;
1659
Alan Coxb65b5b52006-06-27 02:54:05 -07001660 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 panelp = brdp->panels[0];
1662 iobase = panelp->iobase;
1663 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1664 handled = 1;
1665 (* panelp->isr)(panelp, iobase);
1666 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001667 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 return handled;
1669}
1670
1671/*****************************************************************************/
1672
1673/*
1674 * Interrupt service routine for ECH-AT board types.
1675 */
1676
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001677static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001679 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001680 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 int handled = 0;
1682
1683 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1684
1685 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1686 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001687 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 ioaddr = brdp->bnkstataddr[bnknr];
1689 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1690 panelp = brdp->bnk2panel[bnknr];
1691 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1692 }
1693 }
1694 }
1695
1696 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1697
1698 return handled;
1699}
1700
1701/*****************************************************************************/
1702
1703/*
1704 * Interrupt service routine for ECH-MCA board types.
1705 */
1706
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001707static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001709 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001710 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 int handled = 0;
1712
1713 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1714 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001715 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 ioaddr = brdp->bnkstataddr[bnknr];
1717 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1718 panelp = brdp->bnk2panel[bnknr];
1719 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1720 }
1721 }
1722 }
1723 return handled;
1724}
1725
1726/*****************************************************************************/
1727
1728/*
1729 * Interrupt service routine for ECH-PCI board types.
1730 */
1731
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001732static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001734 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001735 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 int handled = 0;
1737
1738 while (1) {
1739 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001740 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1742 ioaddr = brdp->bnkstataddr[bnknr];
1743 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1744 panelp = brdp->bnk2panel[bnknr];
1745 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1746 recheck++;
1747 handled = 1;
1748 }
1749 }
1750 if (! recheck)
1751 break;
1752 }
1753 return handled;
1754}
1755
1756/*****************************************************************************/
1757
1758/*
1759 * Interrupt service routine for ECH-8/64-PCI board types.
1760 */
1761
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001762static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001764 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001765 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 int handled = 0;
1767
1768 while (inb(brdp->ioctrl) & 0x1) {
1769 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001770 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 ioaddr = brdp->bnkstataddr[bnknr];
1772 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1773 panelp = brdp->bnk2panel[bnknr];
1774 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1775 }
1776 }
1777 }
1778
1779 return handled;
1780}
1781
1782/*****************************************************************************/
1783
1784/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 * Initialize all the ports on a panel.
1786 */
1787
Jiri Slaby705c1862006-12-08 02:39:11 -08001788static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001790 struct stlport *portp;
1791 unsigned int i;
1792 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793
Jiri Slabya0564e12006-12-08 02:38:37 -08001794 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
1796 chipmask = stl_panelinit(brdp, panelp);
1797
1798/*
1799 * All UART's are initialized (if found!). Now go through and setup
1800 * each ports data structures.
1801 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001802 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001803 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001804 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001806 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 break;
1808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
1810 portp->magic = STL_PORTMAGIC;
1811 portp->portnr = i;
1812 portp->brdnr = panelp->brdnr;
1813 portp->panelnr = panelp->panelnr;
1814 portp->uartp = panelp->uartp;
1815 portp->clk = brdp->clk;
1816 portp->baud_base = STL_BAUDBASE;
1817 portp->close_delay = STL_CLOSEDELAY;
1818 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001819 init_waitqueue_head(&portp->port.open_wait);
1820 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 portp->stats.brd = portp->brdnr;
1822 portp->stats.panel = portp->panelnr;
1823 portp->stats.port = portp->portnr;
1824 panelp->ports[i] = portp;
1825 stl_portinit(brdp, panelp, portp);
1826 }
1827
Jiri Slabyc62429d2006-12-08 02:39:14 -08001828 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829}
1830
Jiri Slaby3b85b342006-12-08 02:39:10 -08001831static void stl_cleanup_panels(struct stlbrd *brdp)
1832{
1833 struct stlpanel *panelp;
1834 struct stlport *portp;
1835 unsigned int j, k;
1836
1837 for (j = 0; j < STL_MAXPANELS; j++) {
1838 panelp = brdp->panels[j];
1839 if (panelp == NULL)
1840 continue;
1841 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1842 portp = panelp->ports[k];
1843 if (portp == NULL)
1844 continue;
Alan Coxf8ae4762008-07-16 21:56:37 +01001845 if (portp->port.tty != NULL)
1846 stl_hangup(portp->port.tty);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001847 kfree(portp->tx.buf);
1848 kfree(portp);
1849 }
1850 kfree(panelp);
1851 }
1852}
1853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854/*****************************************************************************/
1855
1856/*
1857 * Try to find and initialize an EasyIO board.
1858 */
1859
Jiri Slaby705c1862006-12-08 02:39:11 -08001860static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001862 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 unsigned int status;
1864 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001865 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Jiri Slabya0564e12006-12-08 02:38:37 -08001867 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
1869 brdp->ioctrl = brdp->ioaddr1 + 1;
1870 brdp->iostatus = brdp->ioaddr1 + 2;
1871
1872 status = inb(brdp->iostatus);
1873 if ((status & EIO_IDBITMASK) == EIO_MK3)
1874 brdp->ioctrl++;
1875
1876/*
1877 * Handle board specific stuff now. The real difference is PCI
1878 * or not PCI.
1879 */
1880 if (brdp->brdtype == BRD_EASYIOPCI) {
1881 brdp->iosize1 = 0x80;
1882 brdp->iosize2 = 0x80;
1883 name = "serial(EIO-PCI)";
1884 outb(0x41, (brdp->ioaddr2 + 0x4c));
1885 } else {
1886 brdp->iosize1 = 8;
1887 name = "serial(EIO)";
1888 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1889 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1890 printk("STALLION: invalid irq=%d for brd=%d\n",
1891 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001892 retval = -EINVAL;
1893 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 }
1895 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1896 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1897 brdp->ioctrl);
1898 }
1899
Jiri Slaby3b85b342006-12-08 02:39:10 -08001900 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1902 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1903 "%x conflicts with another device\n", brdp->brdnr,
1904 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001905 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 }
1907
1908 if (brdp->iosize2 > 0)
1909 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1910 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1911 "address %x conflicts with another device\n",
1912 brdp->brdnr, brdp->ioaddr2);
1913 printk(KERN_WARNING "STALLION: Warning, also "
1914 "releasing board %d I/O address %x \n",
1915 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001916 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 }
1918
1919/*
1920 * Everything looks OK, so let's go ahead and probe for the hardware.
1921 */
1922 brdp->clk = CD1400_CLK;
1923 brdp->isr = stl_eiointr;
1924
Jiri Slaby3b85b342006-12-08 02:39:10 -08001925 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 switch (status & EIO_IDBITMASK) {
1927 case EIO_8PORTM:
1928 brdp->clk = CD1400_CLK8M;
1929 /* fall thru */
1930 case EIO_8PORTRS:
1931 case EIO_8PORTDI:
1932 brdp->nrports = 8;
1933 break;
1934 case EIO_4PORTRS:
1935 brdp->nrports = 4;
1936 break;
1937 case EIO_MK3:
1938 switch (status & EIO_BRDMASK) {
1939 case ID_BRD4:
1940 brdp->nrports = 4;
1941 break;
1942 case ID_BRD8:
1943 brdp->nrports = 8;
1944 break;
1945 case ID_BRD16:
1946 brdp->nrports = 16;
1947 break;
1948 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001949 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
1951 break;
1952 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001953 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
1955
1956/*
1957 * We have verified that the board is actually present, so now we
1958 * can complete the setup.
1959 */
1960
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001961 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001962 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001964 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001965 retval = -ENOMEM;
1966 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968
1969 panelp->magic = STL_PANELMAGIC;
1970 panelp->brdnr = brdp->brdnr;
1971 panelp->panelnr = 0;
1972 panelp->nrports = brdp->nrports;
1973 panelp->iobase = brdp->ioaddr1;
1974 panelp->hwid = status;
1975 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001976 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 panelp->isr = stl_sc26198intr;
1978 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001979 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 panelp->isr = stl_cd1400eiointr;
1981 }
1982
1983 brdp->panels[0] = panelp;
1984 brdp->nrpanels = 1;
1985 brdp->state |= BRD_FOUND;
1986 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001987 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 printk("STALLION: failed to register interrupt "
1989 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001990 retval = -ENODEV;
1991 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001993
1994 return 0;
1995err_fr:
1996 stl_cleanup_panels(brdp);
1997err_rel2:
1998 if (brdp->iosize2 > 0)
1999 release_region(brdp->ioaddr2, brdp->iosize2);
2000err_rel1:
2001 release_region(brdp->ioaddr1, brdp->iosize1);
2002err:
2003 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004}
2005
2006/*****************************************************************************/
2007
2008/*
2009 * Try to find an ECH board and initialize it. This code is capable of
2010 * dealing with all types of ECH board.
2011 */
2012
Jiri Slaby705c1862006-12-08 02:39:11 -08002013static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002015 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002016 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2017 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 char *name;
2019
Jiri Slabya0564e12006-12-08 02:38:37 -08002020 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
2022 status = 0;
2023 conflict = 0;
2024
2025/*
2026 * Set up the initial board register contents for boards. This varies a
2027 * bit between the different board types. So we need to handle each
2028 * separately. Also do a check that the supplied IRQ is good.
2029 */
2030 switch (brdp->brdtype) {
2031
2032 case BRD_ECH:
2033 brdp->isr = stl_echatintr;
2034 brdp->ioctrl = brdp->ioaddr1 + 1;
2035 brdp->iostatus = brdp->ioaddr1 + 1;
2036 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002037 if ((status & ECH_IDBITMASK) != ECH_ID) {
2038 retval = -ENODEV;
2039 goto err;
2040 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2042 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2043 printk("STALLION: invalid irq=%d for brd=%d\n",
2044 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002045 retval = -EINVAL;
2046 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 }
2048 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2049 status |= (stl_vecmap[brdp->irq] << 1);
2050 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2051 brdp->ioctrlval = ECH_INTENABLE |
2052 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002053 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2055 brdp->iosize1 = 2;
2056 brdp->iosize2 = 32;
2057 name = "serial(EC8/32)";
2058 outb(status, brdp->ioaddr1);
2059 break;
2060
2061 case BRD_ECHMC:
2062 brdp->isr = stl_echmcaintr;
2063 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2064 brdp->iostatus = brdp->ioctrl;
2065 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002066 if ((status & ECH_IDBITMASK) != ECH_ID) {
2067 retval = -ENODEV;
2068 goto err;
2069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2071 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2072 printk("STALLION: invalid irq=%d for brd=%d\n",
2073 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002074 retval = -EINVAL;
2075 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 }
2077 outb(ECHMC_BRDRESET, brdp->ioctrl);
2078 outb(ECHMC_INTENABLE, brdp->ioctrl);
2079 brdp->iosize1 = 64;
2080 name = "serial(EC8/32-MC)";
2081 break;
2082
2083 case BRD_ECHPCI:
2084 brdp->isr = stl_echpciintr;
2085 brdp->ioctrl = brdp->ioaddr1 + 2;
2086 brdp->iosize1 = 4;
2087 brdp->iosize2 = 8;
2088 name = "serial(EC8/32-PCI)";
2089 break;
2090
2091 case BRD_ECH64PCI:
2092 brdp->isr = stl_echpci64intr;
2093 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2094 outb(0x43, (brdp->ioaddr1 + 0x4c));
2095 brdp->iosize1 = 0x80;
2096 brdp->iosize2 = 0x80;
2097 name = "serial(EC8/64-PCI)";
2098 break;
2099
2100 default:
2101 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002102 retval = -EINVAL;
2103 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 }
2105
2106/*
2107 * Check boards for possible IO address conflicts and return fail status
2108 * if an IO conflict found.
2109 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002110 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2112 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2113 "%x conflicts with another device\n", brdp->brdnr,
2114 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002115 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 }
2117
2118 if (brdp->iosize2 > 0)
2119 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2120 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2121 "address %x conflicts with another device\n",
2122 brdp->brdnr, brdp->ioaddr2);
2123 printk(KERN_WARNING "STALLION: Warning, also "
2124 "releasing board %d I/O address %x \n",
2125 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002126 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 }
2128
2129/*
2130 * Scan through the secondary io address space looking for panels.
2131 * As we find'em allocate and initialize panel structures for each.
2132 */
2133 brdp->clk = CD1400_CLK;
2134 brdp->hwid = status;
2135
2136 ioaddr = brdp->ioaddr2;
2137 banknr = 0;
2138 panelnr = 0;
2139 nxtid = 0;
2140
Jiri Slabyc62429d2006-12-08 02:39:14 -08002141 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 if (brdp->brdtype == BRD_ECHPCI) {
2143 outb(nxtid, brdp->ioctrl);
2144 ioaddr = brdp->ioaddr2;
2145 }
2146 status = inb(ioaddr + ECH_PNLSTATUS);
2147 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002148 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002149 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002150 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002152 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002153 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002154 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 panelp->magic = STL_PANELMAGIC;
2157 panelp->brdnr = brdp->brdnr;
2158 panelp->panelnr = panelnr;
2159 panelp->iobase = ioaddr;
2160 panelp->pagenr = nxtid;
2161 panelp->hwid = status;
2162 brdp->bnk2panel[banknr] = panelp;
2163 brdp->bnkpageaddr[banknr] = nxtid;
2164 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2165
2166 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002167 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 panelp->isr = stl_sc26198intr;
2169 if (status & ECH_PNL16PORT) {
2170 panelp->nrports = 16;
2171 brdp->bnk2panel[banknr] = panelp;
2172 brdp->bnkpageaddr[banknr] = nxtid;
2173 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2174 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002175 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002178 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 panelp->isr = stl_cd1400echintr;
2180 if (status & ECH_PNL16PORT) {
2181 panelp->nrports = 16;
2182 panelp->ackmask = 0x80;
2183 if (brdp->brdtype != BRD_ECHPCI)
2184 ioaddr += EREG_BANKSIZE;
2185 brdp->bnk2panel[banknr] = panelp;
2186 brdp->bnkpageaddr[banknr] = ++nxtid;
2187 brdp->bnkstataddr[banknr++] = ioaddr +
2188 ECH_PNLSTATUS;
2189 } else {
2190 panelp->nrports = 8;
2191 panelp->ackmask = 0xc0;
2192 }
2193 }
2194
2195 nxtid++;
2196 ioaddr += EREG_BANKSIZE;
2197 brdp->nrports += panelp->nrports;
2198 brdp->panels[panelnr++] = panelp;
2199 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002200 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2201 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002202 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 }
2205
2206 brdp->nrpanels = panelnr;
2207 brdp->nrbnks = banknr;
2208 if (brdp->brdtype == BRD_ECH)
2209 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2210
2211 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002212 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 printk("STALLION: failed to register interrupt "
2214 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002215 retval = -ENODEV;
2216 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 }
2218
Jiri Slaby3b85b342006-12-08 02:39:10 -08002219 return 0;
2220err_fr:
2221 stl_cleanup_panels(brdp);
2222 if (brdp->iosize2 > 0)
2223 release_region(brdp->ioaddr2, brdp->iosize2);
2224err_rel1:
2225 release_region(brdp->ioaddr1, brdp->iosize1);
2226err:
2227 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228}
2229
2230/*****************************************************************************/
2231
2232/*
2233 * Initialize and configure the specified board.
2234 * Scan through all the boards in the configuration and see what we
2235 * can find. Handle EIO and the ECH boards a little differently here
2236 * since the initial search and setup is very different.
2237 */
2238
Jiri Slaby705c1862006-12-08 02:39:11 -08002239static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002241 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
Jiri Slabya0564e12006-12-08 02:38:37 -08002243 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
2245 switch (brdp->brdtype) {
2246 case BRD_EASYIO:
2247 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002248 retval = stl_initeio(brdp);
2249 if (retval)
2250 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 break;
2252 case BRD_ECH:
2253 case BRD_ECHMC:
2254 case BRD_ECHPCI:
2255 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002256 retval = stl_initech(brdp);
2257 if (retval)
2258 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 break;
2260 default:
2261 printk("STALLION: board=%d is unknown board type=%d\n",
2262 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002263 retval = -ENODEV;
2264 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 }
2266
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 if ((brdp->state & BRD_FOUND) == 0) {
2268 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2269 stl_brdnames[brdp->brdtype], brdp->brdnr,
2270 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002271 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
2273
Jiri Slabyc62429d2006-12-08 02:39:14 -08002274 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002275 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 stl_initports(brdp, brdp->panels[i]);
2277
2278 printk("STALLION: %s found, board=%d io=%x irq=%d "
2279 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2280 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2281 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002282
2283 return 0;
2284err_free:
2285 free_irq(brdp->irq, brdp);
2286
2287 stl_cleanup_panels(brdp);
2288
2289 release_region(brdp->ioaddr1, brdp->iosize1);
2290 if (brdp->iosize2 > 0)
2291 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002292err:
2293 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294}
2295
2296/*****************************************************************************/
2297
2298/*
2299 * Find the next available board number that is free.
2300 */
2301
Jiri Slaby705c1862006-12-08 02:39:11 -08002302static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002304 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
Jiri Slabyc62429d2006-12-08 02:39:14 -08002306 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002307 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 if (i >= stl_nrbrds)
2309 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002310 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002312
2313 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314}
2315
2316/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317/*
2318 * We have a Stallion board. Allocate a board structure and
2319 * initialize it. Read its IO and IRQ resources from PCI
2320 * configuration space.
2321 */
2322
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002323static int __devinit stl_pciprobe(struct pci_dev *pdev,
2324 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002326 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002327 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002328 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002330 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002331 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002332
Jiri Slaby3b85b342006-12-08 02:39:10 -08002333 retval = pci_enable_device(pdev);
2334 if (retval)
2335 goto err;
2336 brdp = stl_allocbrd();
2337 if (brdp == NULL) {
2338 retval = -ENOMEM;
2339 goto err;
2340 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002341 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002342 brdnr = stl_getbrdnr();
2343 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002344 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002346 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002347 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002348 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002350 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002351 stl_brds[brdp->brdnr] = brdp;
2352 mutex_unlock(&stl_brdslock);
2353
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002355 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
2357/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 * We have all resources from the board, so let's setup the actual
2359 * board structure now.
2360 */
2361 switch (brdtype) {
2362 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002363 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2364 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 break;
2366 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002367 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2368 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 break;
2370 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002371 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2372 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 break;
2374 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002375 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 break;
2377 }
2378
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002379 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002380 retval = stl_brdinit(brdp);
2381 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002382 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002384 pci_set_drvdata(pdev, brdp);
2385
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002386 for (i = 0; i < brdp->nrports; i++)
2387 tty_register_device(stl_serial,
2388 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2389
Jiri Slaby3b85b342006-12-08 02:39:10 -08002390 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002391err_null:
2392 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002393err_fr:
2394 kfree(brdp);
2395err:
2396 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397}
2398
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002399static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002401 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002402 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002406 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002408 release_region(brdp->ioaddr1, brdp->iosize1);
2409 if (brdp->iosize2 > 0)
2410 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002412 for (i = 0; i < brdp->nrports; i++)
2413 tty_unregister_device(stl_serial,
2414 brdp->brdnr * STL_MAXPORTS + i);
2415
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002416 stl_brds[brdp->brdnr] = NULL;
2417 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418}
2419
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002420static struct pci_driver stl_pcidriver = {
2421 .name = "stallion",
2422 .id_table = stl_pcibrds,
2423 .probe = stl_pciprobe,
2424 .remove = __devexit_p(stl_pciremove)
2425};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
2427/*****************************************************************************/
2428
2429/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 * Return the board stats structure to user app.
2431 */
2432
2433static int stl_getbrdstats(combrd_t __user *bp)
2434{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002435 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002436 struct stlbrd *brdp;
2437 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002438 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
2440 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2441 return -EFAULT;
2442 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002443 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002445 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002446 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
2448 memset(&stl_brdstats, 0, sizeof(combrd_t));
2449 stl_brdstats.brd = brdp->brdnr;
2450 stl_brdstats.type = brdp->brdtype;
2451 stl_brdstats.hwid = brdp->hwid;
2452 stl_brdstats.state = brdp->state;
2453 stl_brdstats.ioaddr = brdp->ioaddr1;
2454 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2455 stl_brdstats.irq = brdp->irq;
2456 stl_brdstats.nrpanels = brdp->nrpanels;
2457 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002458 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 panelp = brdp->panels[i];
2460 stl_brdstats.panels[i].panel = i;
2461 stl_brdstats.panels[i].hwid = panelp->hwid;
2462 stl_brdstats.panels[i].nrports = panelp->nrports;
2463 }
2464
2465 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2466}
2467
2468/*****************************************************************************/
2469
2470/*
2471 * Resolve the referenced port number into a port struct pointer.
2472 */
2473
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002474static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002476 struct stlbrd *brdp;
2477 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Jiri Slabyc62429d2006-12-08 02:39:14 -08002479 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2480 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002482 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002483 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002484 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002485 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002487 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002488 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002489 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002490 return NULL;
2491 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492}
2493
2494/*****************************************************************************/
2495
2496/*
2497 * Return the port stats structure to user app. A NULL port struct
2498 * pointer passed in means that we need to find out from the app
2499 * what port to get stats for (used through board control device).
2500 */
2501
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002502static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002504 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 unsigned char *head, *tail;
2506 unsigned long flags;
2507
2508 if (!portp) {
2509 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2510 return -EFAULT;
2511 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2512 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002513 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002514 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 }
2516
2517 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002518 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 portp->stats.hwid = portp->hwid;
2520
2521 portp->stats.ttystate = 0;
2522 portp->stats.cflags = 0;
2523 portp->stats.iflags = 0;
2524 portp->stats.oflags = 0;
2525 portp->stats.lflags = 0;
2526 portp->stats.rxbuffered = 0;
2527
Alan Coxb65b5b52006-06-27 02:54:05 -07002528 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +01002529 if (portp->port.tty != NULL)
2530 if (portp->port.tty->driver_data == portp) {
2531 portp->stats.ttystate = portp->port.tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002532 /* No longer available as a statistic */
Alan Coxf8ae4762008-07-16 21:56:37 +01002533 portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
2534 if (portp->port.tty->termios != NULL) {
2535 portp->stats.cflags = portp->port.tty->termios->c_cflag;
2536 portp->stats.iflags = portp->port.tty->termios->c_iflag;
2537 portp->stats.oflags = portp->port.tty->termios->c_oflag;
2538 portp->stats.lflags = portp->port.tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 }
2540 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002541 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
2543 head = portp->tx.head;
2544 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002545 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2546 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2549
2550 return copy_to_user(cp, &portp->stats,
2551 sizeof(comstats_t)) ? -EFAULT : 0;
2552}
2553
2554/*****************************************************************************/
2555
2556/*
2557 * Clear the port stats structure. We also return it zeroed out...
2558 */
2559
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002560static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002562 comstats_t stl_comstats;
2563
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 if (!portp) {
2565 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2566 return -EFAULT;
2567 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2568 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002569 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002570 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 }
2572
2573 memset(&portp->stats, 0, sizeof(comstats_t));
2574 portp->stats.brd = portp->brdnr;
2575 portp->stats.panel = portp->panelnr;
2576 portp->stats.port = portp->portnr;
2577 return copy_to_user(cp, &portp->stats,
2578 sizeof(comstats_t)) ? -EFAULT : 0;
2579}
2580
2581/*****************************************************************************/
2582
2583/*
2584 * Return the entire driver ports structure to a user app.
2585 */
2586
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002587static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002589 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002590 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002592 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 return -EFAULT;
2594 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2595 stl_dummyport.portnr);
2596 if (!portp)
2597 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002598 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599}
2600
2601/*****************************************************************************/
2602
2603/*
2604 * Return the entire driver board structure to a user app.
2605 */
2606
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002607static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002609 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002610 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002612 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002614 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 return -ENODEV;
2616 brdp = stl_brds[stl_dummybrd.brdnr];
2617 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002618 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002619 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620}
2621
2622/*****************************************************************************/
2623
2624/*
2625 * The "staliomem" device is also required to do some special operations
2626 * on the board and/or ports. In this driver it is mostly used for stats
2627 * collection.
2628 */
2629
2630static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2631{
2632 int brdnr, rc;
2633 void __user *argp = (void __user *)arg;
2634
Jiri Slabya0564e12006-12-08 02:38:37 -08002635 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 brdnr = iminor(ip);
2638 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002639 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 rc = 0;
2641
2642 switch (cmd) {
2643 case COM_GETPORTSTATS:
2644 rc = stl_getportstats(NULL, argp);
2645 break;
2646 case COM_CLRPORTSTATS:
2647 rc = stl_clrportstats(NULL, argp);
2648 break;
2649 case COM_GETBRDSTATS:
2650 rc = stl_getbrdstats(argp);
2651 break;
2652 case COM_READPORT:
2653 rc = stl_getportstruct(argp);
2654 break;
2655 case COM_READBOARD:
2656 rc = stl_getbrdstruct(argp);
2657 break;
2658 default:
2659 rc = -ENOIOCTLCMD;
2660 break;
2661 }
2662
Jiri Slabyc62429d2006-12-08 02:39:14 -08002663 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664}
2665
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002666static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 .open = stl_open,
2668 .close = stl_close,
2669 .write = stl_write,
2670 .put_char = stl_putchar,
2671 .flush_chars = stl_flushchars,
2672 .write_room = stl_writeroom,
2673 .chars_in_buffer = stl_charsinbuffer,
2674 .ioctl = stl_ioctl,
2675 .set_termios = stl_settermios,
2676 .throttle = stl_throttle,
2677 .unthrottle = stl_unthrottle,
2678 .stop = stl_stop,
2679 .start = stl_start,
2680 .hangup = stl_hangup,
2681 .flush_buffer = stl_flushbuffer,
2682 .break_ctl = stl_breakctl,
2683 .wait_until_sent = stl_waituntilsent,
2684 .send_xchar = stl_sendxchar,
2685 .read_proc = stl_readproc,
2686 .tiocmget = stl_tiocmget,
2687 .tiocmset = stl_tiocmset,
2688};
2689
2690/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691/* CD1400 HARDWARE FUNCTIONS */
2692/*****************************************************************************/
2693
2694/*
2695 * These functions get/set/update the registers of the cd1400 UARTs.
2696 * Access to the cd1400 registers is via an address/data io port pair.
2697 * (Maybe should make this inline...)
2698 */
2699
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002700static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701{
2702 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002703 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704}
2705
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002706static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002708 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 outb(value, portp->ioaddr + EREG_DATA);
2710}
2711
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002712static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002714 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 if (inb(portp->ioaddr + EREG_DATA) != value) {
2716 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002717 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002719 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720}
2721
2722/*****************************************************************************/
2723
2724/*
2725 * Inbitialize the UARTs in a panel. We don't care what sort of board
2726 * these ports are on - since the port io registers are almost
2727 * identical when dealing with ports.
2728 */
2729
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002730static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
2732 unsigned int gfrcr;
2733 int chipmask, i, j;
2734 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002735 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Jiri Slabya0564e12006-12-08 02:38:37 -08002737 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
Alan Coxb65b5b52006-06-27 02:54:05 -07002739 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 BRDENABLE(panelp->brdnr, panelp->pagenr);
2741
2742/*
2743 * Check that each chip is present and started up OK.
2744 */
2745 chipmask = 0;
2746 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002747 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (brdp->brdtype == BRD_ECHPCI) {
2749 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2750 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002751 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 uartaddr = (i & 0x01) ? 0x080 : 0;
2754 outb((GFRCR + uartaddr), ioaddr);
2755 outb(0, (ioaddr + EREG_DATA));
2756 outb((CCR + uartaddr), ioaddr);
2757 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2758 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2759 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002760 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2762 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002763
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2765 printk("STALLION: cd1400 not responding, "
2766 "brd=%d panel=%d chip=%d\n",
2767 panelp->brdnr, panelp->panelnr, i);
2768 continue;
2769 }
2770 chipmask |= (0x1 << i);
2771 outb((PPR + uartaddr), ioaddr);
2772 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2773 }
2774
2775 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002776 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002777 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778}
2779
2780/*****************************************************************************/
2781
2782/*
2783 * Initialize hardware specific port registers.
2784 */
2785
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002786static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787{
Alan Coxb65b5b52006-06-27 02:54:05 -07002788 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002789 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2790 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791
Jiri Slaby615e4a72006-12-08 02:38:38 -08002792 if ((brdp == NULL) || (panelp == NULL) ||
2793 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 return;
2795
Alan Coxb65b5b52006-06-27 02:54:05 -07002796 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2798 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2799 portp->uartaddr = (portp->portnr & 0x04) << 5;
2800 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2801
2802 BRDENABLE(portp->brdnr, portp->pagenr);
2803 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2804 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2805 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2806 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002807 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808}
2809
2810/*****************************************************************************/
2811
2812/*
2813 * Wait for the command register to be ready. We will poll this,
2814 * since it won't usually take too long to be ready.
2815 */
2816
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002817static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818{
2819 int i;
2820
Jiri Slabyc62429d2006-12-08 02:39:14 -08002821 for (i = 0; i < CCR_MAXWAIT; i++)
2822 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
2825 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2826 portp->portnr, portp->panelnr, portp->brdnr);
2827}
2828
2829/*****************************************************************************/
2830
2831/*
2832 * Set up the cd1400 registers for a port based on the termios port
2833 * settings.
2834 */
2835
Alan Cox606d0992006-12-08 02:38:45 -08002836static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002838 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 unsigned long flags;
2840 unsigned int clkdiv, baudrate;
2841 unsigned char cor1, cor2, cor3;
2842 unsigned char cor4, cor5, ccr;
2843 unsigned char srer, sreron, sreroff;
2844 unsigned char mcor1, mcor2, rtpr;
2845 unsigned char clk, div;
2846
2847 cor1 = 0;
2848 cor2 = 0;
2849 cor3 = 0;
2850 cor4 = 0;
2851 cor5 = 0;
2852 ccr = 0;
2853 rtpr = 0;
2854 clk = 0;
2855 div = 0;
2856 mcor1 = 0;
2857 mcor2 = 0;
2858 sreron = 0;
2859 sreroff = 0;
2860
2861 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002862 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 return;
2864
2865/*
2866 * Set up the RX char ignore mask with those RX error types we
2867 * can ignore. We can get the cd1400 to help us out a little here,
2868 * it will ignore parity errors and breaks for us.
2869 */
2870 portp->rxignoremsk = 0;
2871 if (tiosp->c_iflag & IGNPAR) {
2872 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2873 cor1 |= COR1_PARIGNORE;
2874 }
2875 if (tiosp->c_iflag & IGNBRK) {
2876 portp->rxignoremsk |= ST_BREAK;
2877 cor4 |= COR4_IGNBRK;
2878 }
2879
2880 portp->rxmarkmsk = ST_OVERRUN;
2881 if (tiosp->c_iflag & (INPCK | PARMRK))
2882 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2883 if (tiosp->c_iflag & BRKINT)
2884 portp->rxmarkmsk |= ST_BREAK;
2885
2886/*
2887 * Go through the char size, parity and stop bits and set all the
2888 * option register appropriately.
2889 */
2890 switch (tiosp->c_cflag & CSIZE) {
2891 case CS5:
2892 cor1 |= COR1_CHL5;
2893 break;
2894 case CS6:
2895 cor1 |= COR1_CHL6;
2896 break;
2897 case CS7:
2898 cor1 |= COR1_CHL7;
2899 break;
2900 default:
2901 cor1 |= COR1_CHL8;
2902 break;
2903 }
2904
2905 if (tiosp->c_cflag & CSTOPB)
2906 cor1 |= COR1_STOP2;
2907 else
2908 cor1 |= COR1_STOP1;
2909
2910 if (tiosp->c_cflag & PARENB) {
2911 if (tiosp->c_cflag & PARODD)
2912 cor1 |= (COR1_PARENB | COR1_PARODD);
2913 else
2914 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2915 } else {
2916 cor1 |= COR1_PARNONE;
2917 }
2918
2919/*
2920 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2921 * space for hardware flow control and the like. This should be set to
2922 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2923 * really be based on VTIME.
2924 */
2925 cor3 |= FIFO_RXTHRESHOLD;
2926 rtpr = 2;
2927
2928/*
2929 * Calculate the baud rate timers. For now we will just assume that
2930 * the input and output baud are the same. Could have used a baud
2931 * table here, but this way we can generate virtually any baud rate
2932 * we like!
2933 */
2934 baudrate = tiosp->c_cflag & CBAUD;
2935 if (baudrate & CBAUDEX) {
2936 baudrate &= ~CBAUDEX;
2937 if ((baudrate < 1) || (baudrate > 4))
2938 tiosp->c_cflag &= ~CBAUDEX;
2939 else
2940 baudrate += 15;
2941 }
2942 baudrate = stl_baudrates[baudrate];
2943 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002944 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002946 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002948 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002950 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002952 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 baudrate = (portp->baud_base / portp->custom_divisor);
2954 }
2955 if (baudrate > STL_CD1400MAXBAUD)
2956 baudrate = STL_CD1400MAXBAUD;
2957
2958 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002959 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2960 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 if (clkdiv < 0x100)
2962 break;
2963 }
2964 div = (unsigned char) clkdiv;
2965 }
2966
2967/*
2968 * Check what form of modem signaling is required and set it up.
2969 */
2970 if ((tiosp->c_cflag & CLOCAL) == 0) {
2971 mcor1 |= MCOR1_DCD;
2972 mcor2 |= MCOR2_DCD;
2973 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002974 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002975 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002976 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977
2978/*
2979 * Setup cd1400 enhanced modes if we can. In particular we want to
2980 * handle as much of the flow control as possible automatically. As
2981 * well as saving a few CPU cycles it will also greatly improve flow
2982 * control reliability.
2983 */
2984 if (tiosp->c_iflag & IXON) {
2985 cor2 |= COR2_TXIBE;
2986 cor3 |= COR3_SCD12;
2987 if (tiosp->c_iflag & IXANY)
2988 cor2 |= COR2_IXM;
2989 }
2990
2991 if (tiosp->c_cflag & CRTSCTS) {
2992 cor2 |= COR2_CTSAE;
2993 mcor1 |= FIFO_RTSTHRESHOLD;
2994 }
2995
2996/*
2997 * All cd1400 register values calculated so go through and set
2998 * them all up.
2999 */
3000
Jiri Slabya0564e12006-12-08 02:38:37 -08003001 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003003 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003005 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003007 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3008 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3010 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Alan Coxb65b5b52006-06-27 02:54:05 -07003012 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 BRDENABLE(portp->brdnr, portp->pagenr);
3014 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3015 srer = stl_cd1400getreg(portp, SRER);
3016 stl_cd1400setreg(portp, SRER, 0);
3017 if (stl_cd1400updatereg(portp, COR1, cor1))
3018 ccr = 1;
3019 if (stl_cd1400updatereg(portp, COR2, cor2))
3020 ccr = 1;
3021 if (stl_cd1400updatereg(portp, COR3, cor3))
3022 ccr = 1;
3023 if (ccr) {
3024 stl_cd1400ccrwait(portp);
3025 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3026 }
3027 stl_cd1400setreg(portp, COR4, cor4);
3028 stl_cd1400setreg(portp, COR5, cor5);
3029 stl_cd1400setreg(portp, MCOR1, mcor1);
3030 stl_cd1400setreg(portp, MCOR2, mcor2);
3031 if (baudrate > 0) {
3032 stl_cd1400setreg(portp, TCOR, clk);
3033 stl_cd1400setreg(portp, TBPR, div);
3034 stl_cd1400setreg(portp, RCOR, clk);
3035 stl_cd1400setreg(portp, RBPR, div);
3036 }
3037 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3038 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3039 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3040 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3041 stl_cd1400setreg(portp, RTPR, rtpr);
3042 mcor1 = stl_cd1400getreg(portp, MSVR1);
3043 if (mcor1 & MSVR1_DCD)
3044 portp->sigs |= TIOCM_CD;
3045 else
3046 portp->sigs &= ~TIOCM_CD;
3047 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3048 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003049 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050}
3051
3052/*****************************************************************************/
3053
3054/*
3055 * Set the state of the DTR and RTS signals.
3056 */
3057
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003058static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
3060 unsigned char msvr1, msvr2;
3061 unsigned long flags;
3062
Jiri Slabya0564e12006-12-08 02:38:37 -08003063 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3064 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
3066 msvr1 = 0;
3067 msvr2 = 0;
3068 if (dtr > 0)
3069 msvr1 = MSVR1_DTR;
3070 if (rts > 0)
3071 msvr2 = MSVR2_RTS;
3072
Alan Coxb65b5b52006-06-27 02:54:05 -07003073 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 BRDENABLE(portp->brdnr, portp->pagenr);
3075 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3076 if (rts >= 0)
3077 stl_cd1400setreg(portp, MSVR2, msvr2);
3078 if (dtr >= 0)
3079 stl_cd1400setreg(portp, MSVR1, msvr1);
3080 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003081 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082}
3083
3084/*****************************************************************************/
3085
3086/*
3087 * Return the state of the signals.
3088 */
3089
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003090static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091{
3092 unsigned char msvr1, msvr2;
3093 unsigned long flags;
3094 int sigs;
3095
Jiri Slabya0564e12006-12-08 02:38:37 -08003096 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
Alan Coxb65b5b52006-06-27 02:54:05 -07003098 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 BRDENABLE(portp->brdnr, portp->pagenr);
3100 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3101 msvr1 = stl_cd1400getreg(portp, MSVR1);
3102 msvr2 = stl_cd1400getreg(portp, MSVR2);
3103 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003104 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
3106 sigs = 0;
3107 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3108 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3109 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3110 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3111#if 0
3112 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3113 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3114#else
3115 sigs |= TIOCM_DSR;
3116#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003117 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118}
3119
3120/*****************************************************************************/
3121
3122/*
3123 * Enable/Disable the Transmitter and/or Receiver.
3124 */
3125
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003126static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127{
3128 unsigned char ccr;
3129 unsigned long flags;
3130
Jiri Slabya0564e12006-12-08 02:38:37 -08003131 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3132
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 ccr = 0;
3134
3135 if (tx == 0)
3136 ccr |= CCR_TXDISABLE;
3137 else if (tx > 0)
3138 ccr |= CCR_TXENABLE;
3139 if (rx == 0)
3140 ccr |= CCR_RXDISABLE;
3141 else if (rx > 0)
3142 ccr |= CCR_RXENABLE;
3143
Alan Coxb65b5b52006-06-27 02:54:05 -07003144 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 BRDENABLE(portp->brdnr, portp->pagenr);
3146 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3147 stl_cd1400ccrwait(portp);
3148 stl_cd1400setreg(portp, CCR, ccr);
3149 stl_cd1400ccrwait(portp);
3150 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003151 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152}
3153
3154/*****************************************************************************/
3155
3156/*
3157 * Start/stop the Transmitter and/or Receiver.
3158 */
3159
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003160static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161{
3162 unsigned char sreron, sreroff;
3163 unsigned long flags;
3164
Jiri Slabya0564e12006-12-08 02:38:37 -08003165 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
3167 sreron = 0;
3168 sreroff = 0;
3169 if (tx == 0)
3170 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3171 else if (tx == 1)
3172 sreron |= SRER_TXDATA;
3173 else if (tx >= 2)
3174 sreron |= SRER_TXEMPTY;
3175 if (rx == 0)
3176 sreroff |= SRER_RXDATA;
3177 else if (rx > 0)
3178 sreron |= SRER_RXDATA;
3179
Alan Coxb65b5b52006-06-27 02:54:05 -07003180 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 BRDENABLE(portp->brdnr, portp->pagenr);
3182 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3183 stl_cd1400setreg(portp, SRER,
3184 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3185 BRDDISABLE(portp->brdnr);
3186 if (tx > 0)
3187 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003188 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189}
3190
3191/*****************************************************************************/
3192
3193/*
3194 * Disable all interrupts from this port.
3195 */
3196
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003197static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198{
3199 unsigned long flags;
3200
Jiri Slabya0564e12006-12-08 02:38:37 -08003201 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3202
Alan Coxb65b5b52006-06-27 02:54:05 -07003203 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204 BRDENABLE(portp->brdnr, portp->pagenr);
3205 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3206 stl_cd1400setreg(portp, SRER, 0);
3207 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003208 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209}
3210
3211/*****************************************************************************/
3212
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003213static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214{
3215 unsigned long flags;
3216
Jiri Slabya0564e12006-12-08 02:38:37 -08003217 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218
Alan Coxb65b5b52006-06-27 02:54:05 -07003219 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 BRDENABLE(portp->brdnr, portp->pagenr);
3221 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3222 stl_cd1400setreg(portp, SRER,
3223 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3224 SRER_TXEMPTY));
3225 BRDDISABLE(portp->brdnr);
3226 portp->brklen = len;
3227 if (len == 1)
3228 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003229 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230}
3231
3232/*****************************************************************************/
3233
3234/*
3235 * Take flow control actions...
3236 */
3237
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003238static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239{
3240 struct tty_struct *tty;
3241 unsigned long flags;
3242
Jiri Slabya0564e12006-12-08 02:38:37 -08003243 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
Jiri Slaby615e4a72006-12-08 02:38:38 -08003245 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003247 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003248 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249 return;
3250
Alan Coxb65b5b52006-06-27 02:54:05 -07003251 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 BRDENABLE(portp->brdnr, portp->pagenr);
3253 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3254
3255 if (state) {
3256 if (tty->termios->c_iflag & IXOFF) {
3257 stl_cd1400ccrwait(portp);
3258 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3259 portp->stats.rxxon++;
3260 stl_cd1400ccrwait(portp);
3261 }
3262/*
3263 * Question: should we return RTS to what it was before? It may
3264 * have been set by an ioctl... Suppose not, since if you have
3265 * hardware flow control set then it is pretty silly to go and
3266 * set the RTS line by hand.
3267 */
3268 if (tty->termios->c_cflag & CRTSCTS) {
3269 stl_cd1400setreg(portp, MCOR1,
3270 (stl_cd1400getreg(portp, MCOR1) |
3271 FIFO_RTSTHRESHOLD));
3272 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3273 portp->stats.rxrtson++;
3274 }
3275 } else {
3276 if (tty->termios->c_iflag & IXOFF) {
3277 stl_cd1400ccrwait(portp);
3278 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3279 portp->stats.rxxoff++;
3280 stl_cd1400ccrwait(portp);
3281 }
3282 if (tty->termios->c_cflag & CRTSCTS) {
3283 stl_cd1400setreg(portp, MCOR1,
3284 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3285 stl_cd1400setreg(portp, MSVR2, 0);
3286 portp->stats.rxrtsoff++;
3287 }
3288 }
3289
3290 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003291 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292}
3293
3294/*****************************************************************************/
3295
3296/*
3297 * Send a flow control character...
3298 */
3299
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003300static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301{
3302 struct tty_struct *tty;
3303 unsigned long flags;
3304
Jiri Slabya0564e12006-12-08 02:38:37 -08003305 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Jiri Slaby615e4a72006-12-08 02:38:38 -08003307 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003309 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003310 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311 return;
3312
Alan Coxb65b5b52006-06-27 02:54:05 -07003313 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 BRDENABLE(portp->brdnr, portp->pagenr);
3315 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3316 if (state) {
3317 stl_cd1400ccrwait(portp);
3318 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3319 portp->stats.rxxon++;
3320 stl_cd1400ccrwait(portp);
3321 } else {
3322 stl_cd1400ccrwait(portp);
3323 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3324 portp->stats.rxxoff++;
3325 stl_cd1400ccrwait(portp);
3326 }
3327 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003328 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329}
3330
3331/*****************************************************************************/
3332
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003333static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334{
3335 unsigned long flags;
3336
Jiri Slabya0564e12006-12-08 02:38:37 -08003337 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Jiri Slaby615e4a72006-12-08 02:38:38 -08003339 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 return;
3341
Alan Coxb65b5b52006-06-27 02:54:05 -07003342 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343 BRDENABLE(portp->brdnr, portp->pagenr);
3344 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3345 stl_cd1400ccrwait(portp);
3346 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3347 stl_cd1400ccrwait(portp);
3348 portp->tx.tail = portp->tx.head;
3349 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003350 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351}
3352
3353/*****************************************************************************/
3354
3355/*
3356 * Return the current state of data flow on this port. This is only
3357 * really interresting when determining if data has fully completed
3358 * transmission or not... This is easy for the cd1400, it accurately
3359 * maintains the busy port flag.
3360 */
3361
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003362static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363{
Jiri Slabya0564e12006-12-08 02:38:37 -08003364 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
Jiri Slaby615e4a72006-12-08 02:38:38 -08003366 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003367 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368
Jesper Juhl014c2542006-01-15 02:37:08 +01003369 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370}
3371
3372/*****************************************************************************/
3373
3374/*
3375 * Interrupt service routine for cd1400 EasyIO boards.
3376 */
3377
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003378static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379{
3380 unsigned char svrtype;
3381
Jiri Slabya0564e12006-12-08 02:38:37 -08003382 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Alan Coxb65b5b52006-06-27 02:54:05 -07003384 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 outb(SVRR, iobase);
3386 svrtype = inb(iobase + EREG_DATA);
3387 if (panelp->nrports > 4) {
3388 outb((SVRR + 0x80), iobase);
3389 svrtype |= inb(iobase + EREG_DATA);
3390 }
3391
3392 if (svrtype & SVRR_RX)
3393 stl_cd1400rxisr(panelp, iobase);
3394 else if (svrtype & SVRR_TX)
3395 stl_cd1400txisr(panelp, iobase);
3396 else if (svrtype & SVRR_MDM)
3397 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003398
3399 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400}
3401
3402/*****************************************************************************/
3403
3404/*
3405 * Interrupt service routine for cd1400 panels.
3406 */
3407
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003408static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409{
3410 unsigned char svrtype;
3411
Jiri Slabya0564e12006-12-08 02:38:37 -08003412 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
3414 outb(SVRR, iobase);
3415 svrtype = inb(iobase + EREG_DATA);
3416 outb((SVRR + 0x80), iobase);
3417 svrtype |= inb(iobase + EREG_DATA);
3418 if (svrtype & SVRR_RX)
3419 stl_cd1400rxisr(panelp, iobase);
3420 else if (svrtype & SVRR_TX)
3421 stl_cd1400txisr(panelp, iobase);
3422 else if (svrtype & SVRR_MDM)
3423 stl_cd1400mdmisr(panelp, iobase);
3424}
3425
3426
3427/*****************************************************************************/
3428
3429/*
3430 * Unfortunately we need to handle breaks in the TX data stream, since
3431 * this is the only way to generate them on the cd1400.
3432 */
3433
Jiri Slaby60be4812006-12-08 02:38:40 -08003434static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435{
3436 if (portp->brklen == 1) {
3437 outb((COR2 + portp->uartaddr), ioaddr);
3438 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3439 (ioaddr + EREG_DATA));
3440 outb((TDR + portp->uartaddr), ioaddr);
3441 outb(ETC_CMD, (ioaddr + EREG_DATA));
3442 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3443 outb((SRER + portp->uartaddr), ioaddr);
3444 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3445 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003446 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 } else if (portp->brklen > 1) {
3448 outb((TDR + portp->uartaddr), ioaddr);
3449 outb(ETC_CMD, (ioaddr + EREG_DATA));
3450 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3451 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003452 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 } else {
3454 outb((COR2 + portp->uartaddr), ioaddr);
3455 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3456 (ioaddr + EREG_DATA));
3457 portp->brklen = 0;
3458 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003459 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460}
3461
3462/*****************************************************************************/
3463
3464/*
3465 * Transmit interrupt handler. This has gotta be fast! Handling TX
3466 * chars is pretty simple, stuff as many as possible from the TX buffer
3467 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3468 * are embedded as commands in the data stream. Oh no, had to use a goto!
3469 * This could be optimized more, will do when I get time...
3470 * In practice it is possible that interrupts are enabled but that the
3471 * port has been hung up. Need to handle not having any TX buffer here,
3472 * this is done by using the side effect that head and tail will also
3473 * be NULL if the buffer has been freed.
3474 */
3475
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003476static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003478 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 int len, stlen;
3480 char *head, *tail;
3481 unsigned char ioack, srer;
3482
Jiri Slabya0564e12006-12-08 02:38:37 -08003483 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
3485 ioack = inb(ioaddr + EREG_TXACK);
3486 if (((ioack & panelp->ackmask) != 0) ||
3487 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3488 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3489 return;
3490 }
3491 portp = panelp->ports[(ioack >> 3)];
3492
3493/*
3494 * Unfortunately we need to handle breaks in the data stream, since
3495 * this is the only way to generate them on the cd1400. Do it now if
3496 * a break is to be sent.
3497 */
3498 if (portp->brklen != 0)
3499 if (stl_cd1400breakisr(portp, ioaddr))
3500 goto stl_txalldone;
3501
3502 head = portp->tx.head;
3503 tail = portp->tx.tail;
3504 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3505 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3506 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3507 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01003508 if (portp->port.tty)
3509 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 }
3511
3512 if (len == 0) {
3513 outb((SRER + portp->uartaddr), ioaddr);
3514 srer = inb(ioaddr + EREG_DATA);
3515 if (srer & SRER_TXDATA) {
3516 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3517 } else {
3518 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3519 clear_bit(ASYI_TXBUSY, &portp->istate);
3520 }
3521 outb(srer, (ioaddr + EREG_DATA));
3522 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003523 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003525 stlen = min_t(unsigned int, len,
3526 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 outb((TDR + portp->uartaddr), ioaddr);
3528 outsb((ioaddr + EREG_DATA), tail, stlen);
3529 len -= stlen;
3530 tail += stlen;
3531 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3532 tail = portp->tx.buf;
3533 if (len > 0) {
3534 outsb((ioaddr + EREG_DATA), tail, len);
3535 tail += len;
3536 }
3537 portp->tx.tail = tail;
3538 }
3539
3540stl_txalldone:
3541 outb((EOSRR + portp->uartaddr), ioaddr);
3542 outb(0, (ioaddr + EREG_DATA));
3543}
3544
3545/*****************************************************************************/
3546
3547/*
3548 * Receive character interrupt handler. Determine if we have good chars
3549 * or bad chars and then process appropriately. Good chars are easy
3550 * just shove the lot into the RX buffer and set all status byte to 0.
3551 * If a bad RX char then process as required. This routine needs to be
3552 * fast! In practice it is possible that we get an interrupt on a port
3553 * that is closed. This can happen on hangups - since they completely
3554 * shutdown a port not in user context. Need to handle this case.
3555 */
3556
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003557static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003559 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560 struct tty_struct *tty;
3561 unsigned int ioack, len, buflen;
3562 unsigned char status;
3563 char ch;
3564
Jiri Slabya0564e12006-12-08 02:38:37 -08003565 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566
3567 ioack = inb(ioaddr + EREG_RXACK);
3568 if ((ioack & panelp->ackmask) != 0) {
3569 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3570 return;
3571 }
3572 portp = panelp->ports[(ioack >> 3)];
Alan Coxf8ae4762008-07-16 21:56:37 +01003573 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574
3575 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3576 outb((RDCR + portp->uartaddr), ioaddr);
3577 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003578 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003579 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 outb((RDSR + portp->uartaddr), ioaddr);
3581 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3582 portp->stats.rxlost += len;
3583 portp->stats.rxtotal += len;
3584 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003585 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003587 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003589 tty_prepare_flip_string(tty, &ptr, len);
3590 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 tty_schedule_flip(tty);
3592 portp->stats.rxtotal += len;
3593 }
3594 }
3595 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3596 outb((RDSR + portp->uartaddr), ioaddr);
3597 status = inb(ioaddr + EREG_DATA);
3598 ch = inb(ioaddr + EREG_DATA);
3599 if (status & ST_PARITY)
3600 portp->stats.rxparity++;
3601 if (status & ST_FRAMING)
3602 portp->stats.rxframing++;
3603 if (status & ST_OVERRUN)
3604 portp->stats.rxoverrun++;
3605 if (status & ST_BREAK)
3606 portp->stats.rxbreaks++;
3607 if (status & ST_SCHARMASK) {
3608 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3609 portp->stats.txxon++;
3610 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3611 portp->stats.txxoff++;
3612 goto stl_rxalldone;
3613 }
Alan Cox33f0f882006-01-09 20:54:13 -08003614 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 if (portp->rxmarkmsk & status) {
3616 if (status & ST_BREAK) {
3617 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003618 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 do_SAK(tty);
3620 BRDENABLE(portp->brdnr, portp->pagenr);
3621 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003622 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003624 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003626 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003628 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003630 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003632 tty_insert_flip_char(tty, ch, status);
3633 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 }
3635 } else {
3636 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3637 return;
3638 }
3639
3640stl_rxalldone:
3641 outb((EOSRR + portp->uartaddr), ioaddr);
3642 outb(0, (ioaddr + EREG_DATA));
3643}
3644
3645/*****************************************************************************/
3646
3647/*
3648 * Modem interrupt handler. The is called when the modem signal line
3649 * (DCD) has changed state. Leave most of the work to the off-level
3650 * processing routine.
3651 */
3652
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003653static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003655 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 unsigned int ioack;
3657 unsigned char misr;
3658
Jiri Slabya0564e12006-12-08 02:38:37 -08003659 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
3661 ioack = inb(ioaddr + EREG_MDACK);
3662 if (((ioack & panelp->ackmask) != 0) ||
3663 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3664 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3665 return;
3666 }
3667 portp = panelp->ports[(ioack >> 3)];
3668
3669 outb((MISR + portp->uartaddr), ioaddr);
3670 misr = inb(ioaddr + EREG_DATA);
3671 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003672 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 portp->stats.modem++;
3674 }
3675
3676 outb((EOSRR + portp->uartaddr), ioaddr);
3677 outb(0, (ioaddr + EREG_DATA));
3678}
3679
3680/*****************************************************************************/
3681/* SC26198 HARDWARE FUNCTIONS */
3682/*****************************************************************************/
3683
3684/*
3685 * These functions get/set/update the registers of the sc26198 UARTs.
3686 * Access to the sc26198 registers is via an address/data io port pair.
3687 * (Maybe should make this inline...)
3688 */
3689
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003690static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691{
3692 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003693 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694}
3695
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003696static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697{
3698 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3699 outb(value, (portp->ioaddr + XP_DATA));
3700}
3701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003702static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703{
3704 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3705 if (inb(portp->ioaddr + XP_DATA) != value) {
3706 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003707 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003709 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710}
3711
3712/*****************************************************************************/
3713
3714/*
3715 * Functions to get and set the sc26198 global registers.
3716 */
3717
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003718static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719{
3720 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003721 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722}
3723
3724#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003725static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726{
3727 outb(regnr, (portp->ioaddr + XP_ADDR));
3728 outb(value, (portp->ioaddr + XP_DATA));
3729}
3730#endif
3731
3732/*****************************************************************************/
3733
3734/*
3735 * Inbitialize the UARTs in a panel. We don't care what sort of board
3736 * these ports are on - since the port io registers are almost
3737 * identical when dealing with ports.
3738 */
3739
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003740static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741{
3742 int chipmask, i;
3743 int nrchips, ioaddr;
3744
Jiri Slabya0564e12006-12-08 02:38:37 -08003745 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746
3747 BRDENABLE(panelp->brdnr, panelp->pagenr);
3748
3749/*
3750 * Check that each chip is present and started up OK.
3751 */
3752 chipmask = 0;
3753 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3754 if (brdp->brdtype == BRD_ECHPCI)
3755 outb(panelp->pagenr, brdp->ioctrl);
3756
Jiri Slabyc62429d2006-12-08 02:39:14 -08003757 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 ioaddr = panelp->iobase + (i * 4);
3759 outb(SCCR, (ioaddr + XP_ADDR));
3760 outb(CR_RESETALL, (ioaddr + XP_DATA));
3761 outb(TSTR, (ioaddr + XP_ADDR));
3762 if (inb(ioaddr + XP_DATA) != 0) {
3763 printk("STALLION: sc26198 not responding, "
3764 "brd=%d panel=%d chip=%d\n",
3765 panelp->brdnr, panelp->panelnr, i);
3766 continue;
3767 }
3768 chipmask |= (0x1 << i);
3769 outb(GCCR, (ioaddr + XP_ADDR));
3770 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3771 outb(WDTRCR, (ioaddr + XP_ADDR));
3772 outb(0xff, (ioaddr + XP_DATA));
3773 }
3774
3775 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003776 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777}
3778
3779/*****************************************************************************/
3780
3781/*
3782 * Initialize hardware specific port registers.
3783 */
3784
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003785static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786{
Jiri Slabya0564e12006-12-08 02:38:37 -08003787 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3788 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789
Jiri Slaby615e4a72006-12-08 02:38:38 -08003790 if ((brdp == NULL) || (panelp == NULL) ||
3791 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 return;
3793
3794 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3795 portp->uartaddr = (portp->portnr & 0x07) << 4;
3796 portp->pagenr = panelp->pagenr;
3797 portp->hwid = 0x1;
3798
3799 BRDENABLE(portp->brdnr, portp->pagenr);
3800 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3801 BRDDISABLE(portp->brdnr);
3802}
3803
3804/*****************************************************************************/
3805
3806/*
3807 * Set up the sc26198 registers for a port based on the termios port
3808 * settings.
3809 */
3810
Alan Cox606d0992006-12-08 02:38:45 -08003811static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003813 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 unsigned long flags;
3815 unsigned int baudrate;
3816 unsigned char mr0, mr1, mr2, clk;
3817 unsigned char imron, imroff, iopr, ipr;
3818
3819 mr0 = 0;
3820 mr1 = 0;
3821 mr2 = 0;
3822 clk = 0;
3823 iopr = 0;
3824 imron = 0;
3825 imroff = 0;
3826
3827 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003828 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 return;
3830
3831/*
3832 * Set up the RX char ignore mask with those RX error types we
3833 * can ignore.
3834 */
3835 portp->rxignoremsk = 0;
3836 if (tiosp->c_iflag & IGNPAR)
3837 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3838 SR_RXOVERRUN);
3839 if (tiosp->c_iflag & IGNBRK)
3840 portp->rxignoremsk |= SR_RXBREAK;
3841
3842 portp->rxmarkmsk = SR_RXOVERRUN;
3843 if (tiosp->c_iflag & (INPCK | PARMRK))
3844 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3845 if (tiosp->c_iflag & BRKINT)
3846 portp->rxmarkmsk |= SR_RXBREAK;
3847
3848/*
3849 * Go through the char size, parity and stop bits and set all the
3850 * option register appropriately.
3851 */
3852 switch (tiosp->c_cflag & CSIZE) {
3853 case CS5:
3854 mr1 |= MR1_CS5;
3855 break;
3856 case CS6:
3857 mr1 |= MR1_CS6;
3858 break;
3859 case CS7:
3860 mr1 |= MR1_CS7;
3861 break;
3862 default:
3863 mr1 |= MR1_CS8;
3864 break;
3865 }
3866
3867 if (tiosp->c_cflag & CSTOPB)
3868 mr2 |= MR2_STOP2;
3869 else
3870 mr2 |= MR2_STOP1;
3871
3872 if (tiosp->c_cflag & PARENB) {
3873 if (tiosp->c_cflag & PARODD)
3874 mr1 |= (MR1_PARENB | MR1_PARODD);
3875 else
3876 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003877 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
3880 mr1 |= MR1_ERRBLOCK;
3881
3882/*
3883 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3884 * space for hardware flow control and the like. This should be set to
3885 * VMIN.
3886 */
3887 mr2 |= MR2_RXFIFOHALF;
3888
3889/*
3890 * Calculate the baud rate timers. For now we will just assume that
3891 * the input and output baud are the same. The sc26198 has a fixed
3892 * baud rate table, so only discrete baud rates possible.
3893 */
3894 baudrate = tiosp->c_cflag & CBAUD;
3895 if (baudrate & CBAUDEX) {
3896 baudrate &= ~CBAUDEX;
3897 if ((baudrate < 1) || (baudrate > 4))
3898 tiosp->c_cflag &= ~CBAUDEX;
3899 else
3900 baudrate += 15;
3901 }
3902 baudrate = stl_baudrates[baudrate];
3903 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003904 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003906 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003908 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003910 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003912 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 baudrate = (portp->baud_base / portp->custom_divisor);
3914 }
3915 if (baudrate > STL_SC26198MAXBAUD)
3916 baudrate = STL_SC26198MAXBAUD;
3917
Jiri Slabyc62429d2006-12-08 02:39:14 -08003918 if (baudrate > 0)
3919 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 if (baudrate <= sc26198_baudtable[clk])
3921 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923/*
3924 * Check what form of modem signaling is required and set it up.
3925 */
3926 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003927 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 } else {
3929 iopr |= IOPR_DCDCOS;
3930 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003931 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 }
3933
3934/*
3935 * Setup sc26198 enhanced modes if we can. In particular we want to
3936 * handle as much of the flow control as possible automatically. As
3937 * well as saving a few CPU cycles it will also greatly improve flow
3938 * control reliability.
3939 */
3940 if (tiosp->c_iflag & IXON) {
3941 mr0 |= MR0_SWFTX | MR0_SWFT;
3942 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003943 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003945
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 if (tiosp->c_iflag & IXOFF)
3947 mr0 |= MR0_SWFRX;
3948
3949 if (tiosp->c_cflag & CRTSCTS) {
3950 mr2 |= MR2_AUTOCTS;
3951 mr1 |= MR1_AUTORTS;
3952 }
3953
3954/*
3955 * All sc26198 register values calculated so go through and set
3956 * them all up.
3957 */
3958
Jiri Slabya0564e12006-12-08 02:38:37 -08003959 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003961 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3962 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3963 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3965 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966
Alan Coxb65b5b52006-06-27 02:54:05 -07003967 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 BRDENABLE(portp->brdnr, portp->pagenr);
3969 stl_sc26198setreg(portp, IMR, 0);
3970 stl_sc26198updatereg(portp, MR0, mr0);
3971 stl_sc26198updatereg(portp, MR1, mr1);
3972 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3973 stl_sc26198updatereg(portp, MR2, mr2);
3974 stl_sc26198updatereg(portp, IOPIOR,
3975 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3976
3977 if (baudrate > 0) {
3978 stl_sc26198setreg(portp, TXCSR, clk);
3979 stl_sc26198setreg(portp, RXCSR, clk);
3980 }
3981
3982 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3983 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3984
3985 ipr = stl_sc26198getreg(portp, IPR);
3986 if (ipr & IPR_DCD)
3987 portp->sigs &= ~TIOCM_CD;
3988 else
3989 portp->sigs |= TIOCM_CD;
3990
3991 portp->imr = (portp->imr & ~imroff) | imron;
3992 stl_sc26198setreg(portp, IMR, portp->imr);
3993 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003994 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995}
3996
3997/*****************************************************************************/
3998
3999/*
4000 * Set the state of the DTR and RTS signals.
4001 */
4002
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004003static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004{
4005 unsigned char iopioron, iopioroff;
4006 unsigned long flags;
4007
Jiri Slabya0564e12006-12-08 02:38:37 -08004008 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4009 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
4011 iopioron = 0;
4012 iopioroff = 0;
4013 if (dtr == 0)
4014 iopioroff |= IPR_DTR;
4015 else if (dtr > 0)
4016 iopioron |= IPR_DTR;
4017 if (rts == 0)
4018 iopioroff |= IPR_RTS;
4019 else if (rts > 0)
4020 iopioron |= IPR_RTS;
4021
Alan Coxb65b5b52006-06-27 02:54:05 -07004022 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 BRDENABLE(portp->brdnr, portp->pagenr);
4024 stl_sc26198setreg(portp, IOPIOR,
4025 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4026 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004027 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028}
4029
4030/*****************************************************************************/
4031
4032/*
4033 * Return the state of the signals.
4034 */
4035
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004036static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037{
4038 unsigned char ipr;
4039 unsigned long flags;
4040 int sigs;
4041
Jiri Slabya0564e12006-12-08 02:38:37 -08004042 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
Alan Coxb65b5b52006-06-27 02:54:05 -07004044 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 BRDENABLE(portp->brdnr, portp->pagenr);
4046 ipr = stl_sc26198getreg(portp, IPR);
4047 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004048 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
4050 sigs = 0;
4051 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4052 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4053 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4054 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4055 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004056 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057}
4058
4059/*****************************************************************************/
4060
4061/*
4062 * Enable/Disable the Transmitter and/or Receiver.
4063 */
4064
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004065static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066{
4067 unsigned char ccr;
4068 unsigned long flags;
4069
Jiri Slabya0564e12006-12-08 02:38:37 -08004070 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
4072 ccr = portp->crenable;
4073 if (tx == 0)
4074 ccr &= ~CR_TXENABLE;
4075 else if (tx > 0)
4076 ccr |= CR_TXENABLE;
4077 if (rx == 0)
4078 ccr &= ~CR_RXENABLE;
4079 else if (rx > 0)
4080 ccr |= CR_RXENABLE;
4081
Alan Coxb65b5b52006-06-27 02:54:05 -07004082 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 BRDENABLE(portp->brdnr, portp->pagenr);
4084 stl_sc26198setreg(portp, SCCR, ccr);
4085 BRDDISABLE(portp->brdnr);
4086 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004087 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088}
4089
4090/*****************************************************************************/
4091
4092/*
4093 * Start/stop the Transmitter and/or Receiver.
4094 */
4095
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004096static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097{
4098 unsigned char imr;
4099 unsigned long flags;
4100
Jiri Slabya0564e12006-12-08 02:38:37 -08004101 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
4103 imr = portp->imr;
4104 if (tx == 0)
4105 imr &= ~IR_TXRDY;
4106 else if (tx == 1)
4107 imr |= IR_TXRDY;
4108 if (rx == 0)
4109 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4110 else if (rx > 0)
4111 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4112
Alan Coxb65b5b52006-06-27 02:54:05 -07004113 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 BRDENABLE(portp->brdnr, portp->pagenr);
4115 stl_sc26198setreg(portp, IMR, imr);
4116 BRDDISABLE(portp->brdnr);
4117 portp->imr = imr;
4118 if (tx > 0)
4119 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004120 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121}
4122
4123/*****************************************************************************/
4124
4125/*
4126 * Disable all interrupts from this port.
4127 */
4128
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004129static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130{
4131 unsigned long flags;
4132
Jiri Slabya0564e12006-12-08 02:38:37 -08004133 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Alan Coxb65b5b52006-06-27 02:54:05 -07004135 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136 BRDENABLE(portp->brdnr, portp->pagenr);
4137 portp->imr = 0;
4138 stl_sc26198setreg(portp, IMR, 0);
4139 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004140 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141}
4142
4143/*****************************************************************************/
4144
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004145static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146{
4147 unsigned long flags;
4148
Jiri Slabya0564e12006-12-08 02:38:37 -08004149 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150
Alan Coxb65b5b52006-06-27 02:54:05 -07004151 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 BRDENABLE(portp->brdnr, portp->pagenr);
4153 if (len == 1) {
4154 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4155 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004156 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004158
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004160 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161}
4162
4163/*****************************************************************************/
4164
4165/*
4166 * Take flow control actions...
4167 */
4168
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004169static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170{
4171 struct tty_struct *tty;
4172 unsigned long flags;
4173 unsigned char mr0;
4174
Jiri Slabya0564e12006-12-08 02:38:37 -08004175 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Jiri Slaby615e4a72006-12-08 02:38:38 -08004177 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004179 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004180 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181 return;
4182
Alan Coxb65b5b52006-06-27 02:54:05 -07004183 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 BRDENABLE(portp->brdnr, portp->pagenr);
4185
4186 if (state) {
4187 if (tty->termios->c_iflag & IXOFF) {
4188 mr0 = stl_sc26198getreg(portp, MR0);
4189 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4190 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4191 mr0 |= MR0_SWFRX;
4192 portp->stats.rxxon++;
4193 stl_sc26198wait(portp);
4194 stl_sc26198setreg(portp, MR0, mr0);
4195 }
4196/*
4197 * Question: should we return RTS to what it was before? It may
4198 * have been set by an ioctl... Suppose not, since if you have
4199 * hardware flow control set then it is pretty silly to go and
4200 * set the RTS line by hand.
4201 */
4202 if (tty->termios->c_cflag & CRTSCTS) {
4203 stl_sc26198setreg(portp, MR1,
4204 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4205 stl_sc26198setreg(portp, IOPIOR,
4206 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4207 portp->stats.rxrtson++;
4208 }
4209 } else {
4210 if (tty->termios->c_iflag & IXOFF) {
4211 mr0 = stl_sc26198getreg(portp, MR0);
4212 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4213 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4214 mr0 &= ~MR0_SWFRX;
4215 portp->stats.rxxoff++;
4216 stl_sc26198wait(portp);
4217 stl_sc26198setreg(portp, MR0, mr0);
4218 }
4219 if (tty->termios->c_cflag & CRTSCTS) {
4220 stl_sc26198setreg(portp, MR1,
4221 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4222 stl_sc26198setreg(portp, IOPIOR,
4223 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4224 portp->stats.rxrtsoff++;
4225 }
4226 }
4227
4228 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004229 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230}
4231
4232/*****************************************************************************/
4233
4234/*
4235 * Send a flow control character.
4236 */
4237
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004238static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239{
4240 struct tty_struct *tty;
4241 unsigned long flags;
4242 unsigned char mr0;
4243
Jiri Slabya0564e12006-12-08 02:38:37 -08004244 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Jiri Slaby615e4a72006-12-08 02:38:38 -08004246 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004248 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004249 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 return;
4251
Alan Coxb65b5b52006-06-27 02:54:05 -07004252 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 BRDENABLE(portp->brdnr, portp->pagenr);
4254 if (state) {
4255 mr0 = stl_sc26198getreg(portp, MR0);
4256 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4257 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4258 mr0 |= MR0_SWFRX;
4259 portp->stats.rxxon++;
4260 stl_sc26198wait(portp);
4261 stl_sc26198setreg(portp, MR0, mr0);
4262 } else {
4263 mr0 = stl_sc26198getreg(portp, MR0);
4264 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4265 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4266 mr0 &= ~MR0_SWFRX;
4267 portp->stats.rxxoff++;
4268 stl_sc26198wait(portp);
4269 stl_sc26198setreg(portp, MR0, mr0);
4270 }
4271 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004272 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273}
4274
4275/*****************************************************************************/
4276
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004277static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278{
4279 unsigned long flags;
4280
Jiri Slabya0564e12006-12-08 02:38:37 -08004281 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Jiri Slaby615e4a72006-12-08 02:38:38 -08004283 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 return;
4285
Alan Coxb65b5b52006-06-27 02:54:05 -07004286 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 BRDENABLE(portp->brdnr, portp->pagenr);
4288 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4289 stl_sc26198setreg(portp, SCCR, portp->crenable);
4290 BRDDISABLE(portp->brdnr);
4291 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004292 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293}
4294
4295/*****************************************************************************/
4296
4297/*
4298 * Return the current state of data flow on this port. This is only
4299 * really interresting when determining if data has fully completed
4300 * transmission or not... The sc26198 interrupt scheme cannot
4301 * determine when all data has actually drained, so we need to
4302 * check the port statusy register to be sure.
4303 */
4304
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004305static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306{
4307 unsigned long flags;
4308 unsigned char sr;
4309
Jiri Slabya0564e12006-12-08 02:38:37 -08004310 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311
Jiri Slaby615e4a72006-12-08 02:38:38 -08004312 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004313 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004315 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316
Alan Coxb65b5b52006-06-27 02:54:05 -07004317 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318 BRDENABLE(portp->brdnr, portp->pagenr);
4319 sr = stl_sc26198getreg(portp, SR);
4320 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004321 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Jesper Juhl014c2542006-01-15 02:37:08 +01004323 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324}
4325
4326/*****************************************************************************/
4327
4328/*
4329 * Delay for a small amount of time, to give the sc26198 a chance
4330 * to process a command...
4331 */
4332
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004333static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334{
4335 int i;
4336
Jiri Slabya0564e12006-12-08 02:38:37 -08004337 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Jiri Slaby615e4a72006-12-08 02:38:38 -08004339 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340 return;
4341
Jiri Slabyc62429d2006-12-08 02:39:14 -08004342 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 stl_sc26198getglobreg(portp, TSTR);
4344}
4345
4346/*****************************************************************************/
4347
4348/*
4349 * If we are TX flow controlled and in IXANY mode then we may
4350 * need to unflow control here. We gotta do this because of the
4351 * automatic flow control modes of the sc26198.
4352 */
4353
Jiri Slaby60be4812006-12-08 02:38:40 -08004354static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355{
4356 unsigned char mr0;
4357
4358 mr0 = stl_sc26198getreg(portp, MR0);
4359 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4360 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4361 stl_sc26198wait(portp);
4362 stl_sc26198setreg(portp, MR0, mr0);
4363 clear_bit(ASYI_TXFLOWED, &portp->istate);
4364}
4365
4366/*****************************************************************************/
4367
4368/*
4369 * Interrupt service routine for sc26198 panels.
4370 */
4371
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004372static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004374 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 unsigned int iack;
4376
Alan Coxb65b5b52006-06-27 02:54:05 -07004377 spin_lock(&brd_lock);
4378
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379/*
4380 * Work around bug in sc26198 chip... Cannot have A6 address
4381 * line of UART high, else iack will be returned as 0.
4382 */
4383 outb(0, (iobase + 1));
4384
4385 iack = inb(iobase + XP_IACK);
4386 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4387
4388 if (iack & IVR_RXDATA)
4389 stl_sc26198rxisr(portp, iack);
4390 else if (iack & IVR_TXDATA)
4391 stl_sc26198txisr(portp);
4392 else
4393 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004394
4395 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396}
4397
4398/*****************************************************************************/
4399
4400/*
4401 * Transmit interrupt handler. This has gotta be fast! Handling TX
4402 * chars is pretty simple, stuff as many as possible from the TX buffer
4403 * into the sc26198 FIFO.
4404 * In practice it is possible that interrupts are enabled but that the
4405 * port has been hung up. Need to handle not having any TX buffer here,
4406 * this is done by using the side effect that head and tail will also
4407 * be NULL if the buffer has been freed.
4408 */
4409
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004410static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411{
4412 unsigned int ioaddr;
4413 unsigned char mr0;
4414 int len, stlen;
4415 char *head, *tail;
4416
Jiri Slabya0564e12006-12-08 02:38:37 -08004417 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
4419 ioaddr = portp->ioaddr;
4420 head = portp->tx.head;
4421 tail = portp->tx.tail;
4422 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4423 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4424 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4425 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01004426 if (portp->port.tty)
4427 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 }
4429
4430 if (len == 0) {
4431 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4432 mr0 = inb(ioaddr + XP_DATA);
4433 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4434 portp->imr &= ~IR_TXRDY;
4435 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4436 outb(portp->imr, (ioaddr + XP_DATA));
4437 clear_bit(ASYI_TXBUSY, &portp->istate);
4438 } else {
4439 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4440 outb(mr0, (ioaddr + XP_DATA));
4441 }
4442 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004443 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004445 stlen = min_t(unsigned int, len,
4446 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447 outb(GTXFIFO, (ioaddr + XP_ADDR));
4448 outsb((ioaddr + XP_DATA), tail, stlen);
4449 len -= stlen;
4450 tail += stlen;
4451 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4452 tail = portp->tx.buf;
4453 if (len > 0) {
4454 outsb((ioaddr + XP_DATA), tail, len);
4455 tail += len;
4456 }
4457 portp->tx.tail = tail;
4458 }
4459}
4460
4461/*****************************************************************************/
4462
4463/*
4464 * Receive character interrupt handler. Determine if we have good chars
4465 * or bad chars and then process appropriately. Good chars are easy
4466 * just shove the lot into the RX buffer and set all status byte to 0.
4467 * If a bad RX char then process as required. This routine needs to be
4468 * fast! In practice it is possible that we get an interrupt on a port
4469 * that is closed. This can happen on hangups - since they completely
4470 * shutdown a port not in user context. Need to handle this case.
4471 */
4472
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004473static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 struct tty_struct *tty;
4476 unsigned int len, buflen, ioaddr;
4477
Jiri Slabya0564e12006-12-08 02:38:37 -08004478 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Alan Coxf8ae4762008-07-16 21:56:37 +01004480 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 ioaddr = portp->ioaddr;
4482 outb(GIBCR, (ioaddr + XP_ADDR));
4483 len = inb(ioaddr + XP_DATA) + 1;
4484
4485 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004486 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004487 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 outb(GRXFIFO, (ioaddr + XP_ADDR));
4489 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4490 portp->stats.rxlost += len;
4491 portp->stats.rxtotal += len;
4492 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004493 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004495 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004497 tty_prepare_flip_string(tty, &ptr, len);
4498 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 tty_schedule_flip(tty);
4500 portp->stats.rxtotal += len;
4501 }
4502 }
4503 } else {
4504 stl_sc26198rxbadchars(portp);
4505 }
4506
4507/*
4508 * If we are TX flow controlled and in IXANY mode then we may need
4509 * to unflow control here. We gotta do this because of the automatic
4510 * flow control modes of the sc26198.
4511 */
4512 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004513 if ((tty != NULL) &&
4514 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 (tty->termios->c_iflag & IXANY)) {
4516 stl_sc26198txunflow(portp, tty);
4517 }
4518 }
4519}
4520
4521/*****************************************************************************/
4522
4523/*
4524 * Process an RX bad character.
4525 */
4526
Jiri Slaby60be4812006-12-08 02:38:40 -08004527static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528{
4529 struct tty_struct *tty;
4530 unsigned int ioaddr;
4531
Alan Coxf8ae4762008-07-16 21:56:37 +01004532 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 ioaddr = portp->ioaddr;
4534
4535 if (status & SR_RXPARITY)
4536 portp->stats.rxparity++;
4537 if (status & SR_RXFRAMING)
4538 portp->stats.rxframing++;
4539 if (status & SR_RXOVERRUN)
4540 portp->stats.rxoverrun++;
4541 if (status & SR_RXBREAK)
4542 portp->stats.rxbreaks++;
4543
Jiri Slaby615e4a72006-12-08 02:38:38 -08004544 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 ((portp->rxignoremsk & status) == 0)) {
4546 if (portp->rxmarkmsk & status) {
4547 if (status & SR_RXBREAK) {
4548 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004549 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 do_SAK(tty);
4551 BRDENABLE(portp->brdnr, portp->pagenr);
4552 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004553 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004555 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004557 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004559 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004561 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563
Alan Cox33f0f882006-01-09 20:54:13 -08004564 tty_insert_flip_char(tty, ch, status);
4565 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
4567 if (status == 0)
4568 portp->stats.rxtotal++;
4569 }
4570}
4571
4572/*****************************************************************************/
4573
4574/*
4575 * Process all characters in the RX FIFO of the UART. Check all char
4576 * status bytes as well, and process as required. We need to check
4577 * all bytes in the FIFO, in case some more enter the FIFO while we
4578 * are here. To get the exact character error type we need to switch
4579 * into CHAR error mode (that is why we need to make sure we empty
4580 * the FIFO).
4581 */
4582
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004583static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584{
4585 unsigned char status, mr1;
4586 char ch;
4587
4588/*
4589 * To get the precise error type for each character we must switch
4590 * back into CHAR error mode.
4591 */
4592 mr1 = stl_sc26198getreg(portp, MR1);
4593 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4594
4595 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4596 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4597 ch = stl_sc26198getreg(portp, RXFIFO);
4598 stl_sc26198rxbadch(portp, status, ch);
4599 }
4600
4601/*
4602 * To get correct interrupt class we must switch back into BLOCK
4603 * error mode.
4604 */
4605 stl_sc26198setreg(portp, MR1, mr1);
4606}
4607
4608/*****************************************************************************/
4609
4610/*
4611 * Other interrupt handler. This includes modem signals, flow
4612 * control actions, etc. Most stuff is left to off-level interrupt
4613 * processing time.
4614 */
4615
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004616static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617{
4618 unsigned char cir, ipr, xisr;
4619
Jiri Slabya0564e12006-12-08 02:38:37 -08004620 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621
4622 cir = stl_sc26198getglobreg(portp, CIR);
4623
4624 switch (cir & CIR_SUBTYPEMASK) {
4625 case CIR_SUBCOS:
4626 ipr = stl_sc26198getreg(portp, IPR);
4627 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004628 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 portp->stats.modem++;
4630 }
4631 break;
4632 case CIR_SUBXONXOFF:
4633 xisr = stl_sc26198getreg(portp, XISR);
4634 if (xisr & XISR_RXXONGOT) {
4635 set_bit(ASYI_TXFLOWED, &portp->istate);
4636 portp->stats.txxoff++;
4637 }
4638 if (xisr & XISR_RXXOFFGOT) {
4639 clear_bit(ASYI_TXFLOWED, &portp->istate);
4640 portp->stats.txxon++;
4641 }
4642 break;
4643 case CIR_SUBBREAK:
4644 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4645 stl_sc26198rxbadchars(portp);
4646 break;
4647 default:
4648 break;
4649 }
4650}
4651
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004652static void stl_free_isabrds(void)
4653{
4654 struct stlbrd *brdp;
4655 unsigned int i;
4656
4657 for (i = 0; i < stl_nrbrds; i++) {
4658 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4659 continue;
4660
4661 free_irq(brdp->irq, brdp);
4662
4663 stl_cleanup_panels(brdp);
4664
4665 release_region(brdp->ioaddr1, brdp->iosize1);
4666 if (brdp->iosize2 > 0)
4667 release_region(brdp->ioaddr2, brdp->iosize2);
4668
4669 kfree(brdp);
4670 stl_brds[i] = NULL;
4671 }
4672}
4673
Jiri Slaby23b85a12006-12-08 02:38:40 -08004674/*
4675 * Loadable module initialization stuff.
4676 */
4677static int __init stallion_module_init(void)
4678{
Jiri Slaby843b5682006-12-08 02:39:12 -08004679 struct stlbrd *brdp;
4680 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004681 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004682 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004683
4684 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4685
4686 spin_lock_init(&stallion_lock);
4687 spin_lock_init(&brd_lock);
4688
Jiri Slabye4151092007-06-08 13:46:52 -07004689 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4690 if (!stl_serial) {
4691 retval = -ENOMEM;
4692 goto err;
4693 }
4694
4695 stl_serial->owner = THIS_MODULE;
4696 stl_serial->driver_name = stl_drvname;
4697 stl_serial->name = "ttyE";
4698 stl_serial->major = STL_SERIALMAJOR;
4699 stl_serial->minor_start = 0;
4700 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4701 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4702 stl_serial->init_termios = stl_deftermios;
4703 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4704 tty_set_operations(stl_serial, &stl_ops);
4705
4706 retval = tty_register_driver(stl_serial);
4707 if (retval) {
4708 printk("STALLION: failed to register serial driver\n");
4709 goto err_frtty;
4710 }
4711
Jiri Slaby843b5682006-12-08 02:39:12 -08004712/*
4713 * Find any dynamically supported boards. That is via module load
4714 * line options.
4715 */
4716 for (i = stl_nrbrds; i < stl_nargs; i++) {
4717 memset(&conf, 0, sizeof(conf));
4718 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4719 continue;
4720 if ((brdp = stl_allocbrd()) == NULL)
4721 continue;
4722 brdp->brdnr = i;
4723 brdp->brdtype = conf.brdtype;
4724 brdp->ioaddr1 = conf.ioaddr1;
4725 brdp->ioaddr2 = conf.ioaddr2;
4726 brdp->irq = conf.irq;
4727 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004728 stl_brds[brdp->brdnr] = brdp;
4729 if (stl_brdinit(brdp)) {
4730 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004731 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004732 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004733 for (j = 0; j < brdp->nrports; j++)
4734 tty_register_device(stl_serial,
4735 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004736 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004737 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004738 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004739
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004740 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004741 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004742 if (retval && stl_nrbrds == 0) {
4743 printk(KERN_ERR "STALLION: can't register pci driver\n");
4744 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004745 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004746
4747/*
4748 * Set up a character driver for per board stuff. This is mainly used
4749 * to do stats ioctls on the ports.
4750 */
4751 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4752 printk("STALLION: failed to register serial board device\n");
4753
4754 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004755 if (IS_ERR(stallion_class))
4756 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004757 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004758 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4759 "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004760
Jiri Slaby23b85a12006-12-08 02:38:40 -08004761 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004762err_unrtty:
4763 tty_unregister_driver(stl_serial);
4764err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004765 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004766err:
4767 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004768}
4769
4770static void __exit stallion_module_exit(void)
4771{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004772 struct stlbrd *brdp;
4773 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004774
4775 pr_debug("cleanup_module()\n");
4776
4777 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4778 stl_drvversion);
4779
4780/*
4781 * Free up all allocated resources used by the ports. This includes
4782 * memory and interrupts. As part of this process we will also do
4783 * a hangup on every open port - to try to flush out any processes
4784 * hanging onto ports.
4785 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004786 for (i = 0; i < stl_nrbrds; i++) {
4787 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4788 continue;
4789 for (j = 0; j < brdp->nrports; j++)
4790 tty_unregister_device(stl_serial,
4791 brdp->brdnr * STL_MAXPORTS + j);
4792 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004793
Jiri Slaby23b85a12006-12-08 02:38:40 -08004794 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004795 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004796 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004797 class_destroy(stallion_class);
4798
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004799 pci_unregister_driver(&stl_pcidriver);
4800
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004801 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004802
4803 tty_unregister_driver(stl_serial);
4804 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004805}
4806
4807module_init(stallion_module_init);
4808module_exit(stallion_module_exit);
4809
4810MODULE_AUTHOR("Greg Ungerer");
4811MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4812MODULE_LICENSE("GPL");