blob: 0243efb0be957df493937e1fbfb5ad44b215d486 [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
1028static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1029{
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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 return;
1038 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001039 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001041 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return;
1043
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;
1056}
1057
1058/*****************************************************************************/
1059
1060/*
1061 * If there are any characters in the buffer then make sure that TX
1062 * interrupts are on and get'em out. Normally used after the putchar
1063 * routine has been called.
1064 */
1065
1066static void stl_flushchars(struct tty_struct *tty)
1067{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001068 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Jiri Slabya0564e12006-12-08 02:38:37 -08001070 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Jiri Slaby615e4a72006-12-08 02:38:38 -08001072 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 return;
1074 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001075 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001077 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 return;
1079
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 stl_startrxtx(portp, -1, 1);
1081}
1082
1083/*****************************************************************************/
1084
1085static int stl_writeroom(struct tty_struct *tty)
1086{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001087 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 char *head, *tail;
1089
Jiri Slabya0564e12006-12-08 02:38:37 -08001090 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091
Jiri Slaby615e4a72006-12-08 02:38:38 -08001092 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001093 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001095 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001096 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001097 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001098 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 head = portp->tx.head;
1101 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001102 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
1105/*****************************************************************************/
1106
1107/*
1108 * Return number of chars in the TX buffer. Normally we would just
1109 * calculate the number of chars in the buffer and return that, but if
1110 * the buffer is empty and TX interrupts are still on then we return
1111 * that the buffer still has 1 char in it. This way whoever called us
1112 * will not think that ALL chars have drained - since the UART still
1113 * must have some chars in it (we are busy after all).
1114 */
1115
1116static int stl_charsinbuffer(struct tty_struct *tty)
1117{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001118 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 unsigned int size;
1120 char *head, *tail;
1121
Jiri Slabya0564e12006-12-08 02:38:37 -08001122 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Jiri Slaby615e4a72006-12-08 02:38:38 -08001124 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001125 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001127 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001128 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001129 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001130 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
1132 head = portp->tx.head;
1133 tail = portp->tx.tail;
1134 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1135 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1136 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001137 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138}
1139
1140/*****************************************************************************/
1141
1142/*
1143 * Generate the serial struct info.
1144 */
1145
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001146static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147{
1148 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001149 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
Jiri Slabya0564e12006-12-08 02:38:37 -08001151 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
1153 memset(&sio, 0, sizeof(struct serial_struct));
1154 sio.line = portp->portnr;
1155 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001156 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 sio.baud_base = portp->baud_base;
1158 sio.close_delay = portp->close_delay;
1159 sio.closing_wait = portp->closing_wait;
1160 sio.custom_divisor = portp->custom_divisor;
1161 sio.hub6 = 0;
1162 if (portp->uartp == &stl_cd1400uart) {
1163 sio.type = PORT_CIRRUS;
1164 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1165 } else {
1166 sio.type = PORT_UNKNOWN;
1167 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1168 }
1169
1170 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001171 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 sio.irq = brdp->irq;
1173
1174 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1175}
1176
1177/*****************************************************************************/
1178
1179/*
1180 * Set port according to the serial struct info.
1181 * At this point we do not do any auto-configure stuff, so we will
1182 * just quietly ignore any requests to change irq, etc.
1183 */
1184
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001185static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
1187 struct serial_struct sio;
1188
Jiri Slabya0564e12006-12-08 02:38:37 -08001189 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
1191 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1192 return -EFAULT;
1193 if (!capable(CAP_SYS_ADMIN)) {
1194 if ((sio.baud_base != portp->baud_base) ||
1195 (sio.close_delay != portp->close_delay) ||
1196 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001197 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001198 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 }
1200
Alan Coxf8ae4762008-07-16 21:56:37 +01001201 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 (sio.flags & ASYNC_USR_MASK);
1203 portp->baud_base = sio.baud_base;
1204 portp->close_delay = sio.close_delay;
1205 portp->closing_wait = sio.closing_wait;
1206 portp->custom_divisor = sio.custom_divisor;
Alan Coxf8ae4762008-07-16 21:56:37 +01001207 stl_setport(portp, portp->port.tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001208 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209}
1210
1211/*****************************************************************************/
1212
1213static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1214{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001215 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Jiri Slaby615e4a72006-12-08 02:38:38 -08001217 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001218 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001220 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001221 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001223 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225 return stl_getsignals(portp);
1226}
1227
1228static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1229 unsigned int set, unsigned int clear)
1230{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001231 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 int rts = -1, dtr = -1;
1233
Jiri Slaby615e4a72006-12-08 02:38:38 -08001234 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001235 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001237 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001238 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001240 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
1242 if (set & TIOCM_RTS)
1243 rts = 1;
1244 if (set & TIOCM_DTR)
1245 dtr = 1;
1246 if (clear & TIOCM_RTS)
1247 rts = 0;
1248 if (clear & TIOCM_DTR)
1249 dtr = 0;
1250
1251 stl_setsignals(portp, dtr, rts);
1252 return 0;
1253}
1254
1255static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1256{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001257 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 unsigned int ival;
1259 int rc;
1260 void __user *argp = (void __user *)arg;
1261
Jiri Slabya0564e12006-12-08 02:38:37 -08001262 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1263 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Jiri Slaby615e4a72006-12-08 02:38:38 -08001265 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001266 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001268 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001269 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
1271 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001272 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001274 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 rc = 0;
1277
Alan Coxf433c652008-04-30 00:53:23 -07001278 lock_kernel();
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 case TIOCGSERIAL:
1282 rc = stl_getserial(portp, argp);
1283 break;
1284 case TIOCSSERIAL:
1285 rc = stl_setserial(portp, argp);
1286 break;
1287 case COM_GETPORTSTATS:
1288 rc = stl_getportstats(portp, argp);
1289 break;
1290 case COM_CLRPORTSTATS:
1291 rc = stl_clrportstats(portp, argp);
1292 break;
1293 case TIOCSERCONFIG:
1294 case TIOCSERGWILD:
1295 case TIOCSERSWILD:
1296 case TIOCSERGETLSR:
1297 case TIOCSERGSTRUCT:
1298 case TIOCSERGETMULTI:
1299 case TIOCSERSETMULTI:
1300 default:
1301 rc = -ENOIOCTLCMD;
1302 break;
1303 }
Alan Coxf433c652008-04-30 00:53:23 -07001304 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306}
1307
1308/*****************************************************************************/
1309
Jiri Slaby96b066b2006-12-08 02:38:42 -08001310/*
1311 * Start the transmitter again. Just turn TX interrupts back on.
1312 */
1313
1314static void stl_start(struct tty_struct *tty)
1315{
1316 struct stlport *portp;
1317
1318 pr_debug("stl_start(tty=%p)\n", tty);
1319
1320 if (tty == NULL)
1321 return;
1322 portp = tty->driver_data;
1323 if (portp == NULL)
1324 return;
1325 stl_startrxtx(portp, -1, 1);
1326}
1327
1328/*****************************************************************************/
1329
Alan Cox606d0992006-12-08 02:38:45 -08001330static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001332 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001333 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Jiri Slabya0564e12006-12-08 02:38:37 -08001335 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Jiri Slaby615e4a72006-12-08 02:38:38 -08001337 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return;
1339 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001340 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return;
1342
1343 tiosp = tty->termios;
1344 if ((tiosp->c_cflag == old->c_cflag) &&
1345 (tiosp->c_iflag == old->c_iflag))
1346 return;
1347
1348 stl_setport(portp, tiosp);
1349 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1350 -1);
1351 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1352 tty->hw_stopped = 0;
1353 stl_start(tty);
1354 }
1355 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001356 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357}
1358
1359/*****************************************************************************/
1360
1361/*
1362 * Attempt to flow control who ever is sending us data. Based on termios
1363 * settings use software or/and hardware flow control.
1364 */
1365
1366static void stl_throttle(struct tty_struct *tty)
1367{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001368 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slabya0564e12006-12-08 02:38:37 -08001370 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Jiri Slaby615e4a72006-12-08 02:38:38 -08001372 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return;
1374 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001375 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 return;
1377 stl_flowctrl(portp, 0);
1378}
1379
1380/*****************************************************************************/
1381
1382/*
1383 * Unflow control the device sending us data...
1384 */
1385
1386static void stl_unthrottle(struct tty_struct *tty)
1387{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001388 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Jiri Slabya0564e12006-12-08 02:38:37 -08001390 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Jiri Slaby615e4a72006-12-08 02:38:38 -08001392 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 return;
1394 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001395 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 return;
1397 stl_flowctrl(portp, 1);
1398}
1399
1400/*****************************************************************************/
1401
1402/*
1403 * Stop the transmitter. Basically to do this we will just turn TX
1404 * interrupts off.
1405 */
1406
1407static void stl_stop(struct tty_struct *tty)
1408{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001409 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Jiri Slabya0564e12006-12-08 02:38:37 -08001411 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
Jiri Slaby615e4a72006-12-08 02:38:38 -08001413 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 return;
1415 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001416 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 return;
1418 stl_startrxtx(portp, -1, 0);
1419}
1420
1421/*****************************************************************************/
1422
1423/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 * Hangup this port. This is pretty much like closing the port, only
1425 * a little more brutal. No waiting for data to drain. Shutdown the
1426 * port and maybe drop signals.
1427 */
1428
1429static void stl_hangup(struct tty_struct *tty)
1430{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001431 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Jiri Slabya0564e12006-12-08 02:38:37 -08001433 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Jiri Slaby615e4a72006-12-08 02:38:38 -08001435 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 return;
1437 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001438 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 return;
1440
Alan Coxf8ae4762008-07-16 21:56:37 +01001441 portp->port.flags &= ~ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 stl_disableintrs(portp);
1443 if (tty->termios->c_cflag & HUPCL)
1444 stl_setsignals(portp, 0, 0);
1445 stl_enablerxtx(portp, 0, 0);
1446 stl_flushbuffer(tty);
1447 portp->istate = 0;
1448 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001449 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001451 portp->tx.buf = NULL;
1452 portp->tx.head = NULL;
1453 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
Alan Coxf8ae4762008-07-16 21:56:37 +01001455 portp->port.tty = NULL;
1456 portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1457 portp->port.count = 0;
1458 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459}
1460
1461/*****************************************************************************/
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463static void stl_breakctl(struct tty_struct *tty, int state)
1464{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001465 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jiri Slabya0564e12006-12-08 02:38:37 -08001467 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Jiri Slaby615e4a72006-12-08 02:38:38 -08001469 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 return;
1471 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001472 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 return;
1474
1475 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1476}
1477
1478/*****************************************************************************/
1479
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480static void stl_sendxchar(struct tty_struct *tty, char ch)
1481{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001482 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Jiri Slabya0564e12006-12-08 02:38:37 -08001484 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485
Jiri Slaby615e4a72006-12-08 02:38:38 -08001486 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 return;
1488 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001489 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 return;
1491
1492 if (ch == STOP_CHAR(tty))
1493 stl_sendflow(portp, 0);
1494 else if (ch == START_CHAR(tty))
1495 stl_sendflow(portp, 1);
1496 else
1497 stl_putchar(tty, ch);
1498}
1499
1500/*****************************************************************************/
1501
1502#define MAXLINE 80
1503
1504/*
1505 * Format info for a specified port. The line is deliberately limited
1506 * to 80 characters. (If it is too long it will be truncated, if too
1507 * short then padded with spaces).
1508 */
1509
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001510static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511{
1512 char *sp;
1513 int sigs, cnt;
1514
1515 sp = pos;
1516 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1517 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1518 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1519
1520 if (portp->stats.rxframing)
1521 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1522 if (portp->stats.rxparity)
1523 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1524 if (portp->stats.rxbreaks)
1525 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1526 if (portp->stats.rxoverrun)
1527 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1528
1529 sigs = stl_getsignals(portp);
1530 cnt = sprintf(sp, "%s%s%s%s%s ",
1531 (sigs & TIOCM_RTS) ? "|RTS" : "",
1532 (sigs & TIOCM_CTS) ? "|CTS" : "",
1533 (sigs & TIOCM_DTR) ? "|DTR" : "",
1534 (sigs & TIOCM_CD) ? "|DCD" : "",
1535 (sigs & TIOCM_DSR) ? "|DSR" : "");
1536 *sp = ' ';
1537 sp += cnt;
1538
Jiri Slabyc62429d2006-12-08 02:39:14 -08001539 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 *sp++ = ' ';
1541 if (cnt >= MAXLINE)
1542 pos[(MAXLINE - 2)] = '+';
1543 pos[(MAXLINE - 1)] = '\n';
1544
Jesper Juhl014c2542006-01-15 02:37:08 +01001545 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546}
1547
1548/*****************************************************************************/
1549
1550/*
1551 * Port info, read from the /proc file system.
1552 */
1553
1554static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1555{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001556 struct stlbrd *brdp;
1557 struct stlpanel *panelp;
1558 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001559 unsigned int brdnr, panelnr, portnr;
1560 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 char *pos;
1562
Jiri Slabya0564e12006-12-08 02:38:37 -08001563 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1564 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566 pos = page;
1567 totalport = 0;
1568 curoff = 0;
1569
1570 if (off == 0) {
1571 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1572 stl_drvversion);
1573 while (pos < (page + MAXLINE - 1))
1574 *pos++ = ' ';
1575 *pos++ = '\n';
1576 }
1577 curoff = MAXLINE;
1578
1579/*
1580 * We scan through for each board, panel and port. The offset is
1581 * calculated on the fly, and irrelevant ports are skipped.
1582 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001583 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001585 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 continue;
1587 if (brdp->state == 0)
1588 continue;
1589
1590 maxoff = curoff + (brdp->nrports * MAXLINE);
1591 if (off >= maxoff) {
1592 curoff = maxoff;
1593 continue;
1594 }
1595
1596 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001597 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001599 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 continue;
1601
1602 maxoff = curoff + (panelp->nrports * MAXLINE);
1603 if (off >= maxoff) {
1604 curoff = maxoff;
1605 totalport += panelp->nrports;
1606 continue;
1607 }
1608
Jiri Slabyc62429d2006-12-08 02:39:14 -08001609 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 totalport++) {
1611 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001612 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 continue;
1614 if (off >= (curoff += MAXLINE))
1615 continue;
1616 if ((pos - page + MAXLINE) > count)
1617 goto stl_readdone;
1618 pos += stl_portinfo(portp, totalport, pos);
1619 }
1620 }
1621 }
1622
1623 *eof = 1;
1624
1625stl_readdone:
1626 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001627 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628}
1629
1630/*****************************************************************************/
1631
1632/*
1633 * All board interrupts are vectored through here first. This code then
1634 * calls off to the approrpriate board interrupt handlers.
1635 */
1636
David Howells7d12e782006-10-05 14:55:46 +01001637static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001639 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Jeff Garzika6f97b22007-10-31 05:20:49 -04001641 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
1643 return IRQ_RETVAL((* brdp->isr)(brdp));
1644}
1645
1646/*****************************************************************************/
1647
1648/*
1649 * Interrupt service routine for EasyIO board types.
1650 */
1651
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001652static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001654 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 unsigned int iobase;
1656 int handled = 0;
1657
Alan Coxb65b5b52006-06-27 02:54:05 -07001658 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 panelp = brdp->panels[0];
1660 iobase = panelp->iobase;
1661 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1662 handled = 1;
1663 (* panelp->isr)(panelp, iobase);
1664 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001665 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 return handled;
1667}
1668
1669/*****************************************************************************/
1670
1671/*
1672 * Interrupt service routine for ECH-AT board types.
1673 */
1674
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001675static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001677 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001678 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 int handled = 0;
1680
1681 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1682
1683 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1684 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001685 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 ioaddr = brdp->bnkstataddr[bnknr];
1687 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1688 panelp = brdp->bnk2panel[bnknr];
1689 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1690 }
1691 }
1692 }
1693
1694 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1695
1696 return handled;
1697}
1698
1699/*****************************************************************************/
1700
1701/*
1702 * Interrupt service routine for ECH-MCA board types.
1703 */
1704
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001705static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001707 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001708 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 int handled = 0;
1710
1711 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1712 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001713 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 ioaddr = brdp->bnkstataddr[bnknr];
1715 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1716 panelp = brdp->bnk2panel[bnknr];
1717 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1718 }
1719 }
1720 }
1721 return handled;
1722}
1723
1724/*****************************************************************************/
1725
1726/*
1727 * Interrupt service routine for ECH-PCI board types.
1728 */
1729
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001730static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001732 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001733 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 int handled = 0;
1735
1736 while (1) {
1737 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001738 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1740 ioaddr = brdp->bnkstataddr[bnknr];
1741 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1742 panelp = brdp->bnk2panel[bnknr];
1743 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1744 recheck++;
1745 handled = 1;
1746 }
1747 }
1748 if (! recheck)
1749 break;
1750 }
1751 return handled;
1752}
1753
1754/*****************************************************************************/
1755
1756/*
1757 * Interrupt service routine for ECH-8/64-PCI board types.
1758 */
1759
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001760static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001762 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001763 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 int handled = 0;
1765
1766 while (inb(brdp->ioctrl) & 0x1) {
1767 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001768 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 ioaddr = brdp->bnkstataddr[bnknr];
1770 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1771 panelp = brdp->bnk2panel[bnknr];
1772 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1773 }
1774 }
1775 }
1776
1777 return handled;
1778}
1779
1780/*****************************************************************************/
1781
1782/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 * Initialize all the ports on a panel.
1784 */
1785
Jiri Slaby705c1862006-12-08 02:39:11 -08001786static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001788 struct stlport *portp;
1789 unsigned int i;
1790 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
Jiri Slabya0564e12006-12-08 02:38:37 -08001792 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793
1794 chipmask = stl_panelinit(brdp, panelp);
1795
1796/*
1797 * All UART's are initialized (if found!). Now go through and setup
1798 * each ports data structures.
1799 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001800 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001801 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001802 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001804 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 break;
1806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 portp->magic = STL_PORTMAGIC;
1809 portp->portnr = i;
1810 portp->brdnr = panelp->brdnr;
1811 portp->panelnr = panelp->panelnr;
1812 portp->uartp = panelp->uartp;
1813 portp->clk = brdp->clk;
1814 portp->baud_base = STL_BAUDBASE;
1815 portp->close_delay = STL_CLOSEDELAY;
1816 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001817 init_waitqueue_head(&portp->port.open_wait);
1818 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 portp->stats.brd = portp->brdnr;
1820 portp->stats.panel = portp->panelnr;
1821 portp->stats.port = portp->portnr;
1822 panelp->ports[i] = portp;
1823 stl_portinit(brdp, panelp, portp);
1824 }
1825
Jiri Slabyc62429d2006-12-08 02:39:14 -08001826 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827}
1828
Jiri Slaby3b85b342006-12-08 02:39:10 -08001829static void stl_cleanup_panels(struct stlbrd *brdp)
1830{
1831 struct stlpanel *panelp;
1832 struct stlport *portp;
1833 unsigned int j, k;
1834
1835 for (j = 0; j < STL_MAXPANELS; j++) {
1836 panelp = brdp->panels[j];
1837 if (panelp == NULL)
1838 continue;
1839 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1840 portp = panelp->ports[k];
1841 if (portp == NULL)
1842 continue;
Alan Coxf8ae4762008-07-16 21:56:37 +01001843 if (portp->port.tty != NULL)
1844 stl_hangup(portp->port.tty);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001845 kfree(portp->tx.buf);
1846 kfree(portp);
1847 }
1848 kfree(panelp);
1849 }
1850}
1851
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852/*****************************************************************************/
1853
1854/*
1855 * Try to find and initialize an EasyIO board.
1856 */
1857
Jiri Slaby705c1862006-12-08 02:39:11 -08001858static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001860 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 unsigned int status;
1862 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001863 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Jiri Slabya0564e12006-12-08 02:38:37 -08001865 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
1867 brdp->ioctrl = brdp->ioaddr1 + 1;
1868 brdp->iostatus = brdp->ioaddr1 + 2;
1869
1870 status = inb(brdp->iostatus);
1871 if ((status & EIO_IDBITMASK) == EIO_MK3)
1872 brdp->ioctrl++;
1873
1874/*
1875 * Handle board specific stuff now. The real difference is PCI
1876 * or not PCI.
1877 */
1878 if (brdp->brdtype == BRD_EASYIOPCI) {
1879 brdp->iosize1 = 0x80;
1880 brdp->iosize2 = 0x80;
1881 name = "serial(EIO-PCI)";
1882 outb(0x41, (brdp->ioaddr2 + 0x4c));
1883 } else {
1884 brdp->iosize1 = 8;
1885 name = "serial(EIO)";
1886 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1887 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1888 printk("STALLION: invalid irq=%d for brd=%d\n",
1889 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001890 retval = -EINVAL;
1891 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 }
1893 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1894 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1895 brdp->ioctrl);
1896 }
1897
Jiri Slaby3b85b342006-12-08 02:39:10 -08001898 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1900 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1901 "%x conflicts with another device\n", brdp->brdnr,
1902 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001903 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 }
1905
1906 if (brdp->iosize2 > 0)
1907 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1908 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1909 "address %x conflicts with another device\n",
1910 brdp->brdnr, brdp->ioaddr2);
1911 printk(KERN_WARNING "STALLION: Warning, also "
1912 "releasing board %d I/O address %x \n",
1913 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001914 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 }
1916
1917/*
1918 * Everything looks OK, so let's go ahead and probe for the hardware.
1919 */
1920 brdp->clk = CD1400_CLK;
1921 brdp->isr = stl_eiointr;
1922
Jiri Slaby3b85b342006-12-08 02:39:10 -08001923 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 switch (status & EIO_IDBITMASK) {
1925 case EIO_8PORTM:
1926 brdp->clk = CD1400_CLK8M;
1927 /* fall thru */
1928 case EIO_8PORTRS:
1929 case EIO_8PORTDI:
1930 brdp->nrports = 8;
1931 break;
1932 case EIO_4PORTRS:
1933 brdp->nrports = 4;
1934 break;
1935 case EIO_MK3:
1936 switch (status & EIO_BRDMASK) {
1937 case ID_BRD4:
1938 brdp->nrports = 4;
1939 break;
1940 case ID_BRD8:
1941 brdp->nrports = 8;
1942 break;
1943 case ID_BRD16:
1944 brdp->nrports = 16;
1945 break;
1946 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001947 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 }
1949 break;
1950 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001951 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 }
1953
1954/*
1955 * We have verified that the board is actually present, so now we
1956 * can complete the setup.
1957 */
1958
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001959 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001960 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001962 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001963 retval = -ENOMEM;
1964 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966
1967 panelp->magic = STL_PANELMAGIC;
1968 panelp->brdnr = brdp->brdnr;
1969 panelp->panelnr = 0;
1970 panelp->nrports = brdp->nrports;
1971 panelp->iobase = brdp->ioaddr1;
1972 panelp->hwid = status;
1973 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001974 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 panelp->isr = stl_sc26198intr;
1976 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001977 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 panelp->isr = stl_cd1400eiointr;
1979 }
1980
1981 brdp->panels[0] = panelp;
1982 brdp->nrpanels = 1;
1983 brdp->state |= BRD_FOUND;
1984 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001985 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 printk("STALLION: failed to register interrupt "
1987 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001988 retval = -ENODEV;
1989 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001991
1992 return 0;
1993err_fr:
1994 stl_cleanup_panels(brdp);
1995err_rel2:
1996 if (brdp->iosize2 > 0)
1997 release_region(brdp->ioaddr2, brdp->iosize2);
1998err_rel1:
1999 release_region(brdp->ioaddr1, brdp->iosize1);
2000err:
2001 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002}
2003
2004/*****************************************************************************/
2005
2006/*
2007 * Try to find an ECH board and initialize it. This code is capable of
2008 * dealing with all types of ECH board.
2009 */
2010
Jiri Slaby705c1862006-12-08 02:39:11 -08002011static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002013 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002014 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2015 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 char *name;
2017
Jiri Slabya0564e12006-12-08 02:38:37 -08002018 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
2020 status = 0;
2021 conflict = 0;
2022
2023/*
2024 * Set up the initial board register contents for boards. This varies a
2025 * bit between the different board types. So we need to handle each
2026 * separately. Also do a check that the supplied IRQ is good.
2027 */
2028 switch (brdp->brdtype) {
2029
2030 case BRD_ECH:
2031 brdp->isr = stl_echatintr;
2032 brdp->ioctrl = brdp->ioaddr1 + 1;
2033 brdp->iostatus = brdp->ioaddr1 + 1;
2034 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002035 if ((status & ECH_IDBITMASK) != ECH_ID) {
2036 retval = -ENODEV;
2037 goto err;
2038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2040 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2041 printk("STALLION: invalid irq=%d for brd=%d\n",
2042 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002043 retval = -EINVAL;
2044 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 }
2046 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2047 status |= (stl_vecmap[brdp->irq] << 1);
2048 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2049 brdp->ioctrlval = ECH_INTENABLE |
2050 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002051 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2053 brdp->iosize1 = 2;
2054 brdp->iosize2 = 32;
2055 name = "serial(EC8/32)";
2056 outb(status, brdp->ioaddr1);
2057 break;
2058
2059 case BRD_ECHMC:
2060 brdp->isr = stl_echmcaintr;
2061 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2062 brdp->iostatus = brdp->ioctrl;
2063 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002064 if ((status & ECH_IDBITMASK) != ECH_ID) {
2065 retval = -ENODEV;
2066 goto err;
2067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2069 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2070 printk("STALLION: invalid irq=%d for brd=%d\n",
2071 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002072 retval = -EINVAL;
2073 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 }
2075 outb(ECHMC_BRDRESET, brdp->ioctrl);
2076 outb(ECHMC_INTENABLE, brdp->ioctrl);
2077 brdp->iosize1 = 64;
2078 name = "serial(EC8/32-MC)";
2079 break;
2080
2081 case BRD_ECHPCI:
2082 brdp->isr = stl_echpciintr;
2083 brdp->ioctrl = brdp->ioaddr1 + 2;
2084 brdp->iosize1 = 4;
2085 brdp->iosize2 = 8;
2086 name = "serial(EC8/32-PCI)";
2087 break;
2088
2089 case BRD_ECH64PCI:
2090 brdp->isr = stl_echpci64intr;
2091 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2092 outb(0x43, (brdp->ioaddr1 + 0x4c));
2093 brdp->iosize1 = 0x80;
2094 brdp->iosize2 = 0x80;
2095 name = "serial(EC8/64-PCI)";
2096 break;
2097
2098 default:
2099 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002100 retval = -EINVAL;
2101 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 }
2103
2104/*
2105 * Check boards for possible IO address conflicts and return fail status
2106 * if an IO conflict found.
2107 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002108 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2110 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2111 "%x conflicts with another device\n", brdp->brdnr,
2112 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002113 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 }
2115
2116 if (brdp->iosize2 > 0)
2117 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2118 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2119 "address %x conflicts with another device\n",
2120 brdp->brdnr, brdp->ioaddr2);
2121 printk(KERN_WARNING "STALLION: Warning, also "
2122 "releasing board %d I/O address %x \n",
2123 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002124 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
2127/*
2128 * Scan through the secondary io address space looking for panels.
2129 * As we find'em allocate and initialize panel structures for each.
2130 */
2131 brdp->clk = CD1400_CLK;
2132 brdp->hwid = status;
2133
2134 ioaddr = brdp->ioaddr2;
2135 banknr = 0;
2136 panelnr = 0;
2137 nxtid = 0;
2138
Jiri Slabyc62429d2006-12-08 02:39:14 -08002139 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 if (brdp->brdtype == BRD_ECHPCI) {
2141 outb(nxtid, brdp->ioctrl);
2142 ioaddr = brdp->ioaddr2;
2143 }
2144 status = inb(ioaddr + ECH_PNLSTATUS);
2145 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002146 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002147 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002148 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002150 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002151 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002152 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 panelp->magic = STL_PANELMAGIC;
2155 panelp->brdnr = brdp->brdnr;
2156 panelp->panelnr = panelnr;
2157 panelp->iobase = ioaddr;
2158 panelp->pagenr = nxtid;
2159 panelp->hwid = status;
2160 brdp->bnk2panel[banknr] = panelp;
2161 brdp->bnkpageaddr[banknr] = nxtid;
2162 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2163
2164 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002165 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 panelp->isr = stl_sc26198intr;
2167 if (status & ECH_PNL16PORT) {
2168 panelp->nrports = 16;
2169 brdp->bnk2panel[banknr] = panelp;
2170 brdp->bnkpageaddr[banknr] = nxtid;
2171 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2172 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002173 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002176 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 panelp->isr = stl_cd1400echintr;
2178 if (status & ECH_PNL16PORT) {
2179 panelp->nrports = 16;
2180 panelp->ackmask = 0x80;
2181 if (brdp->brdtype != BRD_ECHPCI)
2182 ioaddr += EREG_BANKSIZE;
2183 brdp->bnk2panel[banknr] = panelp;
2184 brdp->bnkpageaddr[banknr] = ++nxtid;
2185 brdp->bnkstataddr[banknr++] = ioaddr +
2186 ECH_PNLSTATUS;
2187 } else {
2188 panelp->nrports = 8;
2189 panelp->ackmask = 0xc0;
2190 }
2191 }
2192
2193 nxtid++;
2194 ioaddr += EREG_BANKSIZE;
2195 brdp->nrports += panelp->nrports;
2196 brdp->panels[panelnr++] = panelp;
2197 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002198 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2199 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002200 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 }
2203
2204 brdp->nrpanels = panelnr;
2205 brdp->nrbnks = banknr;
2206 if (brdp->brdtype == BRD_ECH)
2207 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2208
2209 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002210 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 printk("STALLION: failed to register interrupt "
2212 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002213 retval = -ENODEV;
2214 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 }
2216
Jiri Slaby3b85b342006-12-08 02:39:10 -08002217 return 0;
2218err_fr:
2219 stl_cleanup_panels(brdp);
2220 if (brdp->iosize2 > 0)
2221 release_region(brdp->ioaddr2, brdp->iosize2);
2222err_rel1:
2223 release_region(brdp->ioaddr1, brdp->iosize1);
2224err:
2225 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226}
2227
2228/*****************************************************************************/
2229
2230/*
2231 * Initialize and configure the specified board.
2232 * Scan through all the boards in the configuration and see what we
2233 * can find. Handle EIO and the ECH boards a little differently here
2234 * since the initial search and setup is very different.
2235 */
2236
Jiri Slaby705c1862006-12-08 02:39:11 -08002237static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002239 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
Jiri Slabya0564e12006-12-08 02:38:37 -08002241 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243 switch (brdp->brdtype) {
2244 case BRD_EASYIO:
2245 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002246 retval = stl_initeio(brdp);
2247 if (retval)
2248 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 break;
2250 case BRD_ECH:
2251 case BRD_ECHMC:
2252 case BRD_ECHPCI:
2253 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002254 retval = stl_initech(brdp);
2255 if (retval)
2256 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 break;
2258 default:
2259 printk("STALLION: board=%d is unknown board type=%d\n",
2260 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002261 retval = -ENODEV;
2262 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
2264
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 if ((brdp->state & BRD_FOUND) == 0) {
2266 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2267 stl_brdnames[brdp->brdtype], brdp->brdnr,
2268 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002269 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
2271
Jiri Slabyc62429d2006-12-08 02:39:14 -08002272 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002273 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 stl_initports(brdp, brdp->panels[i]);
2275
2276 printk("STALLION: %s found, board=%d io=%x irq=%d "
2277 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2278 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2279 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002280
2281 return 0;
2282err_free:
2283 free_irq(brdp->irq, brdp);
2284
2285 stl_cleanup_panels(brdp);
2286
2287 release_region(brdp->ioaddr1, brdp->iosize1);
2288 if (brdp->iosize2 > 0)
2289 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002290err:
2291 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292}
2293
2294/*****************************************************************************/
2295
2296/*
2297 * Find the next available board number that is free.
2298 */
2299
Jiri Slaby705c1862006-12-08 02:39:11 -08002300static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002302 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Jiri Slabyc62429d2006-12-08 02:39:14 -08002304 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002305 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 if (i >= stl_nrbrds)
2307 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002308 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002310
2311 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312}
2313
2314/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315/*
2316 * We have a Stallion board. Allocate a board structure and
2317 * initialize it. Read its IO and IRQ resources from PCI
2318 * configuration space.
2319 */
2320
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002321static int __devinit stl_pciprobe(struct pci_dev *pdev,
2322 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002324 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002325 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002326 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002328 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002329 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002330
Jiri Slaby3b85b342006-12-08 02:39:10 -08002331 retval = pci_enable_device(pdev);
2332 if (retval)
2333 goto err;
2334 brdp = stl_allocbrd();
2335 if (brdp == NULL) {
2336 retval = -ENOMEM;
2337 goto err;
2338 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002339 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002340 brdnr = stl_getbrdnr();
2341 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002342 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002344 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002345 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002346 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002348 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002349 stl_brds[brdp->brdnr] = brdp;
2350 mutex_unlock(&stl_brdslock);
2351
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002353 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354
2355/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 * We have all resources from the board, so let's setup the actual
2357 * board structure now.
2358 */
2359 switch (brdtype) {
2360 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002361 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2362 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 break;
2364 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002365 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2366 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 break;
2368 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002369 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2370 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 break;
2372 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002373 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 break;
2375 }
2376
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002377 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002378 retval = stl_brdinit(brdp);
2379 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002380 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002382 pci_set_drvdata(pdev, brdp);
2383
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002384 for (i = 0; i < brdp->nrports; i++)
2385 tty_register_device(stl_serial,
2386 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2387
Jiri Slaby3b85b342006-12-08 02:39:10 -08002388 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002389err_null:
2390 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002391err_fr:
2392 kfree(brdp);
2393err:
2394 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395}
2396
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002397static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002399 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002400 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002402 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002406 release_region(brdp->ioaddr1, brdp->iosize1);
2407 if (brdp->iosize2 > 0)
2408 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002410 for (i = 0; i < brdp->nrports; i++)
2411 tty_unregister_device(stl_serial,
2412 brdp->brdnr * STL_MAXPORTS + i);
2413
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002414 stl_brds[brdp->brdnr] = NULL;
2415 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416}
2417
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002418static struct pci_driver stl_pcidriver = {
2419 .name = "stallion",
2420 .id_table = stl_pcibrds,
2421 .probe = stl_pciprobe,
2422 .remove = __devexit_p(stl_pciremove)
2423};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
2425/*****************************************************************************/
2426
2427/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 * Return the board stats structure to user app.
2429 */
2430
2431static int stl_getbrdstats(combrd_t __user *bp)
2432{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002433 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002434 struct stlbrd *brdp;
2435 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002436 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
2438 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2439 return -EFAULT;
2440 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002441 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002443 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002444 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445
2446 memset(&stl_brdstats, 0, sizeof(combrd_t));
2447 stl_brdstats.brd = brdp->brdnr;
2448 stl_brdstats.type = brdp->brdtype;
2449 stl_brdstats.hwid = brdp->hwid;
2450 stl_brdstats.state = brdp->state;
2451 stl_brdstats.ioaddr = brdp->ioaddr1;
2452 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2453 stl_brdstats.irq = brdp->irq;
2454 stl_brdstats.nrpanels = brdp->nrpanels;
2455 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002456 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 panelp = brdp->panels[i];
2458 stl_brdstats.panels[i].panel = i;
2459 stl_brdstats.panels[i].hwid = panelp->hwid;
2460 stl_brdstats.panels[i].nrports = panelp->nrports;
2461 }
2462
2463 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2464}
2465
2466/*****************************************************************************/
2467
2468/*
2469 * Resolve the referenced port number into a port struct pointer.
2470 */
2471
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002472static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002474 struct stlbrd *brdp;
2475 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Jiri Slabyc62429d2006-12-08 02:39:14 -08002477 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2478 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002480 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002481 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002482 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002483 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002485 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002486 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002487 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002488 return NULL;
2489 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490}
2491
2492/*****************************************************************************/
2493
2494/*
2495 * Return the port stats structure to user app. A NULL port struct
2496 * pointer passed in means that we need to find out from the app
2497 * what port to get stats for (used through board control device).
2498 */
2499
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002500static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002502 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 unsigned char *head, *tail;
2504 unsigned long flags;
2505
2506 if (!portp) {
2507 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2508 return -EFAULT;
2509 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2510 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002511 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002512 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513 }
2514
2515 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002516 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 portp->stats.hwid = portp->hwid;
2518
2519 portp->stats.ttystate = 0;
2520 portp->stats.cflags = 0;
2521 portp->stats.iflags = 0;
2522 portp->stats.oflags = 0;
2523 portp->stats.lflags = 0;
2524 portp->stats.rxbuffered = 0;
2525
Alan Coxb65b5b52006-06-27 02:54:05 -07002526 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +01002527 if (portp->port.tty != NULL)
2528 if (portp->port.tty->driver_data == portp) {
2529 portp->stats.ttystate = portp->port.tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002530 /* No longer available as a statistic */
Alan Coxf8ae4762008-07-16 21:56:37 +01002531 portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
2532 if (portp->port.tty->termios != NULL) {
2533 portp->stats.cflags = portp->port.tty->termios->c_cflag;
2534 portp->stats.iflags = portp->port.tty->termios->c_iflag;
2535 portp->stats.oflags = portp->port.tty->termios->c_oflag;
2536 portp->stats.lflags = portp->port.tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 }
2538 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002539 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 head = portp->tx.head;
2542 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002543 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2544 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545
2546 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2547
2548 return copy_to_user(cp, &portp->stats,
2549 sizeof(comstats_t)) ? -EFAULT : 0;
2550}
2551
2552/*****************************************************************************/
2553
2554/*
2555 * Clear the port stats structure. We also return it zeroed out...
2556 */
2557
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002558static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002560 comstats_t stl_comstats;
2561
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 if (!portp) {
2563 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2564 return -EFAULT;
2565 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2566 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002567 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002568 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 }
2570
2571 memset(&portp->stats, 0, sizeof(comstats_t));
2572 portp->stats.brd = portp->brdnr;
2573 portp->stats.panel = portp->panelnr;
2574 portp->stats.port = portp->portnr;
2575 return copy_to_user(cp, &portp->stats,
2576 sizeof(comstats_t)) ? -EFAULT : 0;
2577}
2578
2579/*****************************************************************************/
2580
2581/*
2582 * Return the entire driver ports structure to a user app.
2583 */
2584
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002585static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002587 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002588 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002590 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 return -EFAULT;
2592 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2593 stl_dummyport.portnr);
2594 if (!portp)
2595 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002596 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597}
2598
2599/*****************************************************************************/
2600
2601/*
2602 * Return the entire driver board structure to a user app.
2603 */
2604
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002605static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002607 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002608 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002610 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002612 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 return -ENODEV;
2614 brdp = stl_brds[stl_dummybrd.brdnr];
2615 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002616 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002617 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618}
2619
2620/*****************************************************************************/
2621
2622/*
2623 * The "staliomem" device is also required to do some special operations
2624 * on the board and/or ports. In this driver it is mostly used for stats
2625 * collection.
2626 */
2627
2628static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2629{
2630 int brdnr, rc;
2631 void __user *argp = (void __user *)arg;
2632
Jiri Slabya0564e12006-12-08 02:38:37 -08002633 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
2635 brdnr = iminor(ip);
2636 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002637 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 rc = 0;
2639
2640 switch (cmd) {
2641 case COM_GETPORTSTATS:
2642 rc = stl_getportstats(NULL, argp);
2643 break;
2644 case COM_CLRPORTSTATS:
2645 rc = stl_clrportstats(NULL, argp);
2646 break;
2647 case COM_GETBRDSTATS:
2648 rc = stl_getbrdstats(argp);
2649 break;
2650 case COM_READPORT:
2651 rc = stl_getportstruct(argp);
2652 break;
2653 case COM_READBOARD:
2654 rc = stl_getbrdstruct(argp);
2655 break;
2656 default:
2657 rc = -ENOIOCTLCMD;
2658 break;
2659 }
2660
Jiri Slabyc62429d2006-12-08 02:39:14 -08002661 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662}
2663
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002664static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 .open = stl_open,
2666 .close = stl_close,
2667 .write = stl_write,
2668 .put_char = stl_putchar,
2669 .flush_chars = stl_flushchars,
2670 .write_room = stl_writeroom,
2671 .chars_in_buffer = stl_charsinbuffer,
2672 .ioctl = stl_ioctl,
2673 .set_termios = stl_settermios,
2674 .throttle = stl_throttle,
2675 .unthrottle = stl_unthrottle,
2676 .stop = stl_stop,
2677 .start = stl_start,
2678 .hangup = stl_hangup,
2679 .flush_buffer = stl_flushbuffer,
2680 .break_ctl = stl_breakctl,
2681 .wait_until_sent = stl_waituntilsent,
2682 .send_xchar = stl_sendxchar,
2683 .read_proc = stl_readproc,
2684 .tiocmget = stl_tiocmget,
2685 .tiocmset = stl_tiocmset,
2686};
2687
2688/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689/* CD1400 HARDWARE FUNCTIONS */
2690/*****************************************************************************/
2691
2692/*
2693 * These functions get/set/update the registers of the cd1400 UARTs.
2694 * Access to the cd1400 registers is via an address/data io port pair.
2695 * (Maybe should make this inline...)
2696 */
2697
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002698static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699{
2700 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002701 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702}
2703
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002704static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002706 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 outb(value, portp->ioaddr + EREG_DATA);
2708}
2709
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002710static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002712 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 if (inb(portp->ioaddr + EREG_DATA) != value) {
2714 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002715 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002717 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718}
2719
2720/*****************************************************************************/
2721
2722/*
2723 * Inbitialize the UARTs in a panel. We don't care what sort of board
2724 * these ports are on - since the port io registers are almost
2725 * identical when dealing with ports.
2726 */
2727
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002728static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
2730 unsigned int gfrcr;
2731 int chipmask, i, j;
2732 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002733 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
Jiri Slabya0564e12006-12-08 02:38:37 -08002735 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Alan Coxb65b5b52006-06-27 02:54:05 -07002737 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 BRDENABLE(panelp->brdnr, panelp->pagenr);
2739
2740/*
2741 * Check that each chip is present and started up OK.
2742 */
2743 chipmask = 0;
2744 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002745 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 if (brdp->brdtype == BRD_ECHPCI) {
2747 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2748 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002749 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 uartaddr = (i & 0x01) ? 0x080 : 0;
2752 outb((GFRCR + uartaddr), ioaddr);
2753 outb(0, (ioaddr + EREG_DATA));
2754 outb((CCR + uartaddr), ioaddr);
2755 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2756 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2757 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002758 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2760 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002761
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2763 printk("STALLION: cd1400 not responding, "
2764 "brd=%d panel=%d chip=%d\n",
2765 panelp->brdnr, panelp->panelnr, i);
2766 continue;
2767 }
2768 chipmask |= (0x1 << i);
2769 outb((PPR + uartaddr), ioaddr);
2770 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2771 }
2772
2773 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002774 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002775 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776}
2777
2778/*****************************************************************************/
2779
2780/*
2781 * Initialize hardware specific port registers.
2782 */
2783
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002784static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785{
Alan Coxb65b5b52006-06-27 02:54:05 -07002786 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002787 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2788 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
Jiri Slaby615e4a72006-12-08 02:38:38 -08002790 if ((brdp == NULL) || (panelp == NULL) ||
2791 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 return;
2793
Alan Coxb65b5b52006-06-27 02:54:05 -07002794 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2796 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2797 portp->uartaddr = (portp->portnr & 0x04) << 5;
2798 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2799
2800 BRDENABLE(portp->brdnr, portp->pagenr);
2801 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2802 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2803 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2804 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002805 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806}
2807
2808/*****************************************************************************/
2809
2810/*
2811 * Wait for the command register to be ready. We will poll this,
2812 * since it won't usually take too long to be ready.
2813 */
2814
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002815static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816{
2817 int i;
2818
Jiri Slabyc62429d2006-12-08 02:39:14 -08002819 for (i = 0; i < CCR_MAXWAIT; i++)
2820 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
2823 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2824 portp->portnr, portp->panelnr, portp->brdnr);
2825}
2826
2827/*****************************************************************************/
2828
2829/*
2830 * Set up the cd1400 registers for a port based on the termios port
2831 * settings.
2832 */
2833
Alan Cox606d0992006-12-08 02:38:45 -08002834static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002836 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 unsigned long flags;
2838 unsigned int clkdiv, baudrate;
2839 unsigned char cor1, cor2, cor3;
2840 unsigned char cor4, cor5, ccr;
2841 unsigned char srer, sreron, sreroff;
2842 unsigned char mcor1, mcor2, rtpr;
2843 unsigned char clk, div;
2844
2845 cor1 = 0;
2846 cor2 = 0;
2847 cor3 = 0;
2848 cor4 = 0;
2849 cor5 = 0;
2850 ccr = 0;
2851 rtpr = 0;
2852 clk = 0;
2853 div = 0;
2854 mcor1 = 0;
2855 mcor2 = 0;
2856 sreron = 0;
2857 sreroff = 0;
2858
2859 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002860 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 return;
2862
2863/*
2864 * Set up the RX char ignore mask with those RX error types we
2865 * can ignore. We can get the cd1400 to help us out a little here,
2866 * it will ignore parity errors and breaks for us.
2867 */
2868 portp->rxignoremsk = 0;
2869 if (tiosp->c_iflag & IGNPAR) {
2870 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2871 cor1 |= COR1_PARIGNORE;
2872 }
2873 if (tiosp->c_iflag & IGNBRK) {
2874 portp->rxignoremsk |= ST_BREAK;
2875 cor4 |= COR4_IGNBRK;
2876 }
2877
2878 portp->rxmarkmsk = ST_OVERRUN;
2879 if (tiosp->c_iflag & (INPCK | PARMRK))
2880 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2881 if (tiosp->c_iflag & BRKINT)
2882 portp->rxmarkmsk |= ST_BREAK;
2883
2884/*
2885 * Go through the char size, parity and stop bits and set all the
2886 * option register appropriately.
2887 */
2888 switch (tiosp->c_cflag & CSIZE) {
2889 case CS5:
2890 cor1 |= COR1_CHL5;
2891 break;
2892 case CS6:
2893 cor1 |= COR1_CHL6;
2894 break;
2895 case CS7:
2896 cor1 |= COR1_CHL7;
2897 break;
2898 default:
2899 cor1 |= COR1_CHL8;
2900 break;
2901 }
2902
2903 if (tiosp->c_cflag & CSTOPB)
2904 cor1 |= COR1_STOP2;
2905 else
2906 cor1 |= COR1_STOP1;
2907
2908 if (tiosp->c_cflag & PARENB) {
2909 if (tiosp->c_cflag & PARODD)
2910 cor1 |= (COR1_PARENB | COR1_PARODD);
2911 else
2912 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2913 } else {
2914 cor1 |= COR1_PARNONE;
2915 }
2916
2917/*
2918 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2919 * space for hardware flow control and the like. This should be set to
2920 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2921 * really be based on VTIME.
2922 */
2923 cor3 |= FIFO_RXTHRESHOLD;
2924 rtpr = 2;
2925
2926/*
2927 * Calculate the baud rate timers. For now we will just assume that
2928 * the input and output baud are the same. Could have used a baud
2929 * table here, but this way we can generate virtually any baud rate
2930 * we like!
2931 */
2932 baudrate = tiosp->c_cflag & CBAUD;
2933 if (baudrate & CBAUDEX) {
2934 baudrate &= ~CBAUDEX;
2935 if ((baudrate < 1) || (baudrate > 4))
2936 tiosp->c_cflag &= ~CBAUDEX;
2937 else
2938 baudrate += 15;
2939 }
2940 baudrate = stl_baudrates[baudrate];
2941 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002942 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002944 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002946 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002948 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002950 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951 baudrate = (portp->baud_base / portp->custom_divisor);
2952 }
2953 if (baudrate > STL_CD1400MAXBAUD)
2954 baudrate = STL_CD1400MAXBAUD;
2955
2956 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002957 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2958 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 if (clkdiv < 0x100)
2960 break;
2961 }
2962 div = (unsigned char) clkdiv;
2963 }
2964
2965/*
2966 * Check what form of modem signaling is required and set it up.
2967 */
2968 if ((tiosp->c_cflag & CLOCAL) == 0) {
2969 mcor1 |= MCOR1_DCD;
2970 mcor2 |= MCOR2_DCD;
2971 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002972 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002973 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002974 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975
2976/*
2977 * Setup cd1400 enhanced modes if we can. In particular we want to
2978 * handle as much of the flow control as possible automatically. As
2979 * well as saving a few CPU cycles it will also greatly improve flow
2980 * control reliability.
2981 */
2982 if (tiosp->c_iflag & IXON) {
2983 cor2 |= COR2_TXIBE;
2984 cor3 |= COR3_SCD12;
2985 if (tiosp->c_iflag & IXANY)
2986 cor2 |= COR2_IXM;
2987 }
2988
2989 if (tiosp->c_cflag & CRTSCTS) {
2990 cor2 |= COR2_CTSAE;
2991 mcor1 |= FIFO_RTSTHRESHOLD;
2992 }
2993
2994/*
2995 * All cd1400 register values calculated so go through and set
2996 * them all up.
2997 */
2998
Jiri Slabya0564e12006-12-08 02:38:37 -08002999 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003001 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003003 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003005 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3006 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3008 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Alan Coxb65b5b52006-06-27 02:54:05 -07003010 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011 BRDENABLE(portp->brdnr, portp->pagenr);
3012 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3013 srer = stl_cd1400getreg(portp, SRER);
3014 stl_cd1400setreg(portp, SRER, 0);
3015 if (stl_cd1400updatereg(portp, COR1, cor1))
3016 ccr = 1;
3017 if (stl_cd1400updatereg(portp, COR2, cor2))
3018 ccr = 1;
3019 if (stl_cd1400updatereg(portp, COR3, cor3))
3020 ccr = 1;
3021 if (ccr) {
3022 stl_cd1400ccrwait(portp);
3023 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3024 }
3025 stl_cd1400setreg(portp, COR4, cor4);
3026 stl_cd1400setreg(portp, COR5, cor5);
3027 stl_cd1400setreg(portp, MCOR1, mcor1);
3028 stl_cd1400setreg(portp, MCOR2, mcor2);
3029 if (baudrate > 0) {
3030 stl_cd1400setreg(portp, TCOR, clk);
3031 stl_cd1400setreg(portp, TBPR, div);
3032 stl_cd1400setreg(portp, RCOR, clk);
3033 stl_cd1400setreg(portp, RBPR, div);
3034 }
3035 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3036 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3037 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3038 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3039 stl_cd1400setreg(portp, RTPR, rtpr);
3040 mcor1 = stl_cd1400getreg(portp, MSVR1);
3041 if (mcor1 & MSVR1_DCD)
3042 portp->sigs |= TIOCM_CD;
3043 else
3044 portp->sigs &= ~TIOCM_CD;
3045 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3046 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003047 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048}
3049
3050/*****************************************************************************/
3051
3052/*
3053 * Set the state of the DTR and RTS signals.
3054 */
3055
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003056static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057{
3058 unsigned char msvr1, msvr2;
3059 unsigned long flags;
3060
Jiri Slabya0564e12006-12-08 02:38:37 -08003061 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3062 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
3064 msvr1 = 0;
3065 msvr2 = 0;
3066 if (dtr > 0)
3067 msvr1 = MSVR1_DTR;
3068 if (rts > 0)
3069 msvr2 = MSVR2_RTS;
3070
Alan Coxb65b5b52006-06-27 02:54:05 -07003071 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 BRDENABLE(portp->brdnr, portp->pagenr);
3073 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3074 if (rts >= 0)
3075 stl_cd1400setreg(portp, MSVR2, msvr2);
3076 if (dtr >= 0)
3077 stl_cd1400setreg(portp, MSVR1, msvr1);
3078 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003079 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080}
3081
3082/*****************************************************************************/
3083
3084/*
3085 * Return the state of the signals.
3086 */
3087
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003088static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089{
3090 unsigned char msvr1, msvr2;
3091 unsigned long flags;
3092 int sigs;
3093
Jiri Slabya0564e12006-12-08 02:38:37 -08003094 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
Alan Coxb65b5b52006-06-27 02:54:05 -07003096 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 BRDENABLE(portp->brdnr, portp->pagenr);
3098 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3099 msvr1 = stl_cd1400getreg(portp, MSVR1);
3100 msvr2 = stl_cd1400getreg(portp, MSVR2);
3101 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003102 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
3104 sigs = 0;
3105 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3106 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3107 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3108 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3109#if 0
3110 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3111 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3112#else
3113 sigs |= TIOCM_DSR;
3114#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003115 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116}
3117
3118/*****************************************************************************/
3119
3120/*
3121 * Enable/Disable the Transmitter and/or Receiver.
3122 */
3123
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003124static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125{
3126 unsigned char ccr;
3127 unsigned long flags;
3128
Jiri Slabya0564e12006-12-08 02:38:37 -08003129 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3130
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 ccr = 0;
3132
3133 if (tx == 0)
3134 ccr |= CCR_TXDISABLE;
3135 else if (tx > 0)
3136 ccr |= CCR_TXENABLE;
3137 if (rx == 0)
3138 ccr |= CCR_RXDISABLE;
3139 else if (rx > 0)
3140 ccr |= CCR_RXENABLE;
3141
Alan Coxb65b5b52006-06-27 02:54:05 -07003142 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 BRDENABLE(portp->brdnr, portp->pagenr);
3144 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3145 stl_cd1400ccrwait(portp);
3146 stl_cd1400setreg(portp, CCR, ccr);
3147 stl_cd1400ccrwait(portp);
3148 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003149 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150}
3151
3152/*****************************************************************************/
3153
3154/*
3155 * Start/stop the Transmitter and/or Receiver.
3156 */
3157
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003158static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159{
3160 unsigned char sreron, sreroff;
3161 unsigned long flags;
3162
Jiri Slabya0564e12006-12-08 02:38:37 -08003163 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
3165 sreron = 0;
3166 sreroff = 0;
3167 if (tx == 0)
3168 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3169 else if (tx == 1)
3170 sreron |= SRER_TXDATA;
3171 else if (tx >= 2)
3172 sreron |= SRER_TXEMPTY;
3173 if (rx == 0)
3174 sreroff |= SRER_RXDATA;
3175 else if (rx > 0)
3176 sreron |= SRER_RXDATA;
3177
Alan Coxb65b5b52006-06-27 02:54:05 -07003178 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 BRDENABLE(portp->brdnr, portp->pagenr);
3180 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3181 stl_cd1400setreg(portp, SRER,
3182 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3183 BRDDISABLE(portp->brdnr);
3184 if (tx > 0)
3185 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003186 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187}
3188
3189/*****************************************************************************/
3190
3191/*
3192 * Disable all interrupts from this port.
3193 */
3194
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003195static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196{
3197 unsigned long flags;
3198
Jiri Slabya0564e12006-12-08 02:38:37 -08003199 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3200
Alan Coxb65b5b52006-06-27 02:54:05 -07003201 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 BRDENABLE(portp->brdnr, portp->pagenr);
3203 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3204 stl_cd1400setreg(portp, SRER, 0);
3205 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003206 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207}
3208
3209/*****************************************************************************/
3210
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003211static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212{
3213 unsigned long flags;
3214
Jiri Slabya0564e12006-12-08 02:38:37 -08003215 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216
Alan Coxb65b5b52006-06-27 02:54:05 -07003217 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 BRDENABLE(portp->brdnr, portp->pagenr);
3219 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3220 stl_cd1400setreg(portp, SRER,
3221 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3222 SRER_TXEMPTY));
3223 BRDDISABLE(portp->brdnr);
3224 portp->brklen = len;
3225 if (len == 1)
3226 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003227 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228}
3229
3230/*****************************************************************************/
3231
3232/*
3233 * Take flow control actions...
3234 */
3235
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003236static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237{
3238 struct tty_struct *tty;
3239 unsigned long flags;
3240
Jiri Slabya0564e12006-12-08 02:38:37 -08003241 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242
Jiri Slaby615e4a72006-12-08 02:38:38 -08003243 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003245 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003246 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 return;
3248
Alan Coxb65b5b52006-06-27 02:54:05 -07003249 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 BRDENABLE(portp->brdnr, portp->pagenr);
3251 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3252
3253 if (state) {
3254 if (tty->termios->c_iflag & IXOFF) {
3255 stl_cd1400ccrwait(portp);
3256 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3257 portp->stats.rxxon++;
3258 stl_cd1400ccrwait(portp);
3259 }
3260/*
3261 * Question: should we return RTS to what it was before? It may
3262 * have been set by an ioctl... Suppose not, since if you have
3263 * hardware flow control set then it is pretty silly to go and
3264 * set the RTS line by hand.
3265 */
3266 if (tty->termios->c_cflag & CRTSCTS) {
3267 stl_cd1400setreg(portp, MCOR1,
3268 (stl_cd1400getreg(portp, MCOR1) |
3269 FIFO_RTSTHRESHOLD));
3270 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3271 portp->stats.rxrtson++;
3272 }
3273 } else {
3274 if (tty->termios->c_iflag & IXOFF) {
3275 stl_cd1400ccrwait(portp);
3276 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3277 portp->stats.rxxoff++;
3278 stl_cd1400ccrwait(portp);
3279 }
3280 if (tty->termios->c_cflag & CRTSCTS) {
3281 stl_cd1400setreg(portp, MCOR1,
3282 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3283 stl_cd1400setreg(portp, MSVR2, 0);
3284 portp->stats.rxrtsoff++;
3285 }
3286 }
3287
3288 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003289 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290}
3291
3292/*****************************************************************************/
3293
3294/*
3295 * Send a flow control character...
3296 */
3297
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003298static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299{
3300 struct tty_struct *tty;
3301 unsigned long flags;
3302
Jiri Slabya0564e12006-12-08 02:38:37 -08003303 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Jiri Slaby615e4a72006-12-08 02:38:38 -08003305 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01003307 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003308 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309 return;
3310
Alan Coxb65b5b52006-06-27 02:54:05 -07003311 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 BRDENABLE(portp->brdnr, portp->pagenr);
3313 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3314 if (state) {
3315 stl_cd1400ccrwait(portp);
3316 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3317 portp->stats.rxxon++;
3318 stl_cd1400ccrwait(portp);
3319 } else {
3320 stl_cd1400ccrwait(portp);
3321 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3322 portp->stats.rxxoff++;
3323 stl_cd1400ccrwait(portp);
3324 }
3325 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003326 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327}
3328
3329/*****************************************************************************/
3330
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003331static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332{
3333 unsigned long flags;
3334
Jiri Slabya0564e12006-12-08 02:38:37 -08003335 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Jiri Slaby615e4a72006-12-08 02:38:38 -08003337 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 return;
3339
Alan Coxb65b5b52006-06-27 02:54:05 -07003340 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 BRDENABLE(portp->brdnr, portp->pagenr);
3342 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3343 stl_cd1400ccrwait(portp);
3344 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3345 stl_cd1400ccrwait(portp);
3346 portp->tx.tail = portp->tx.head;
3347 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003348 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349}
3350
3351/*****************************************************************************/
3352
3353/*
3354 * Return the current state of data flow on this port. This is only
3355 * really interresting when determining if data has fully completed
3356 * transmission or not... This is easy for the cd1400, it accurately
3357 * maintains the busy port flag.
3358 */
3359
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003360static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361{
Jiri Slabya0564e12006-12-08 02:38:37 -08003362 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363
Jiri Slaby615e4a72006-12-08 02:38:38 -08003364 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003365 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366
Jesper Juhl014c2542006-01-15 02:37:08 +01003367 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368}
3369
3370/*****************************************************************************/
3371
3372/*
3373 * Interrupt service routine for cd1400 EasyIO boards.
3374 */
3375
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003376static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377{
3378 unsigned char svrtype;
3379
Jiri Slabya0564e12006-12-08 02:38:37 -08003380 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Alan Coxb65b5b52006-06-27 02:54:05 -07003382 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 outb(SVRR, iobase);
3384 svrtype = inb(iobase + EREG_DATA);
3385 if (panelp->nrports > 4) {
3386 outb((SVRR + 0x80), iobase);
3387 svrtype |= inb(iobase + EREG_DATA);
3388 }
3389
3390 if (svrtype & SVRR_RX)
3391 stl_cd1400rxisr(panelp, iobase);
3392 else if (svrtype & SVRR_TX)
3393 stl_cd1400txisr(panelp, iobase);
3394 else if (svrtype & SVRR_MDM)
3395 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003396
3397 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398}
3399
3400/*****************************************************************************/
3401
3402/*
3403 * Interrupt service routine for cd1400 panels.
3404 */
3405
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003406static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407{
3408 unsigned char svrtype;
3409
Jiri Slabya0564e12006-12-08 02:38:37 -08003410 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
3412 outb(SVRR, iobase);
3413 svrtype = inb(iobase + EREG_DATA);
3414 outb((SVRR + 0x80), iobase);
3415 svrtype |= inb(iobase + EREG_DATA);
3416 if (svrtype & SVRR_RX)
3417 stl_cd1400rxisr(panelp, iobase);
3418 else if (svrtype & SVRR_TX)
3419 stl_cd1400txisr(panelp, iobase);
3420 else if (svrtype & SVRR_MDM)
3421 stl_cd1400mdmisr(panelp, iobase);
3422}
3423
3424
3425/*****************************************************************************/
3426
3427/*
3428 * Unfortunately we need to handle breaks in the TX data stream, since
3429 * this is the only way to generate them on the cd1400.
3430 */
3431
Jiri Slaby60be4812006-12-08 02:38:40 -08003432static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433{
3434 if (portp->brklen == 1) {
3435 outb((COR2 + portp->uartaddr), ioaddr);
3436 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3437 (ioaddr + EREG_DATA));
3438 outb((TDR + portp->uartaddr), ioaddr);
3439 outb(ETC_CMD, (ioaddr + EREG_DATA));
3440 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3441 outb((SRER + portp->uartaddr), ioaddr);
3442 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3443 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003444 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 } else if (portp->brklen > 1) {
3446 outb((TDR + portp->uartaddr), ioaddr);
3447 outb(ETC_CMD, (ioaddr + EREG_DATA));
3448 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3449 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003450 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 } else {
3452 outb((COR2 + portp->uartaddr), ioaddr);
3453 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3454 (ioaddr + EREG_DATA));
3455 portp->brklen = 0;
3456 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003457 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458}
3459
3460/*****************************************************************************/
3461
3462/*
3463 * Transmit interrupt handler. This has gotta be fast! Handling TX
3464 * chars is pretty simple, stuff as many as possible from the TX buffer
3465 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3466 * are embedded as commands in the data stream. Oh no, had to use a goto!
3467 * This could be optimized more, will do when I get time...
3468 * In practice it is possible that interrupts are enabled but that the
3469 * port has been hung up. Need to handle not having any TX buffer here,
3470 * this is done by using the side effect that head and tail will also
3471 * be NULL if the buffer has been freed.
3472 */
3473
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003474static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003476 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 int len, stlen;
3478 char *head, *tail;
3479 unsigned char ioack, srer;
3480
Jiri Slabya0564e12006-12-08 02:38:37 -08003481 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482
3483 ioack = inb(ioaddr + EREG_TXACK);
3484 if (((ioack & panelp->ackmask) != 0) ||
3485 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3486 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3487 return;
3488 }
3489 portp = panelp->ports[(ioack >> 3)];
3490
3491/*
3492 * Unfortunately we need to handle breaks in the data stream, since
3493 * this is the only way to generate them on the cd1400. Do it now if
3494 * a break is to be sent.
3495 */
3496 if (portp->brklen != 0)
3497 if (stl_cd1400breakisr(portp, ioaddr))
3498 goto stl_txalldone;
3499
3500 head = portp->tx.head;
3501 tail = portp->tx.tail;
3502 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3503 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3504 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3505 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01003506 if (portp->port.tty)
3507 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508 }
3509
3510 if (len == 0) {
3511 outb((SRER + portp->uartaddr), ioaddr);
3512 srer = inb(ioaddr + EREG_DATA);
3513 if (srer & SRER_TXDATA) {
3514 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3515 } else {
3516 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3517 clear_bit(ASYI_TXBUSY, &portp->istate);
3518 }
3519 outb(srer, (ioaddr + EREG_DATA));
3520 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003521 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003523 stlen = min_t(unsigned int, len,
3524 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525 outb((TDR + portp->uartaddr), ioaddr);
3526 outsb((ioaddr + EREG_DATA), tail, stlen);
3527 len -= stlen;
3528 tail += stlen;
3529 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3530 tail = portp->tx.buf;
3531 if (len > 0) {
3532 outsb((ioaddr + EREG_DATA), tail, len);
3533 tail += len;
3534 }
3535 portp->tx.tail = tail;
3536 }
3537
3538stl_txalldone:
3539 outb((EOSRR + portp->uartaddr), ioaddr);
3540 outb(0, (ioaddr + EREG_DATA));
3541}
3542
3543/*****************************************************************************/
3544
3545/*
3546 * Receive character interrupt handler. Determine if we have good chars
3547 * or bad chars and then process appropriately. Good chars are easy
3548 * just shove the lot into the RX buffer and set all status byte to 0.
3549 * If a bad RX char then process as required. This routine needs to be
3550 * fast! In practice it is possible that we get an interrupt on a port
3551 * that is closed. This can happen on hangups - since they completely
3552 * shutdown a port not in user context. Need to handle this case.
3553 */
3554
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003555static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003557 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 struct tty_struct *tty;
3559 unsigned int ioack, len, buflen;
3560 unsigned char status;
3561 char ch;
3562
Jiri Slabya0564e12006-12-08 02:38:37 -08003563 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
3565 ioack = inb(ioaddr + EREG_RXACK);
3566 if ((ioack & panelp->ackmask) != 0) {
3567 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3568 return;
3569 }
3570 portp = panelp->ports[(ioack >> 3)];
Alan Coxf8ae4762008-07-16 21:56:37 +01003571 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572
3573 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3574 outb((RDCR + portp->uartaddr), ioaddr);
3575 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003576 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003577 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578 outb((RDSR + portp->uartaddr), ioaddr);
3579 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3580 portp->stats.rxlost += len;
3581 portp->stats.rxtotal += len;
3582 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003583 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003585 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003587 tty_prepare_flip_string(tty, &ptr, len);
3588 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589 tty_schedule_flip(tty);
3590 portp->stats.rxtotal += len;
3591 }
3592 }
3593 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3594 outb((RDSR + portp->uartaddr), ioaddr);
3595 status = inb(ioaddr + EREG_DATA);
3596 ch = inb(ioaddr + EREG_DATA);
3597 if (status & ST_PARITY)
3598 portp->stats.rxparity++;
3599 if (status & ST_FRAMING)
3600 portp->stats.rxframing++;
3601 if (status & ST_OVERRUN)
3602 portp->stats.rxoverrun++;
3603 if (status & ST_BREAK)
3604 portp->stats.rxbreaks++;
3605 if (status & ST_SCHARMASK) {
3606 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3607 portp->stats.txxon++;
3608 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3609 portp->stats.txxoff++;
3610 goto stl_rxalldone;
3611 }
Alan Cox33f0f882006-01-09 20:54:13 -08003612 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 if (portp->rxmarkmsk & status) {
3614 if (status & ST_BREAK) {
3615 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003616 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 do_SAK(tty);
3618 BRDENABLE(portp->brdnr, portp->pagenr);
3619 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003620 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003622 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003624 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003626 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003628 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003630 tty_insert_flip_char(tty, ch, status);
3631 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 }
3633 } else {
3634 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3635 return;
3636 }
3637
3638stl_rxalldone:
3639 outb((EOSRR + portp->uartaddr), ioaddr);
3640 outb(0, (ioaddr + EREG_DATA));
3641}
3642
3643/*****************************************************************************/
3644
3645/*
3646 * Modem interrupt handler. The is called when the modem signal line
3647 * (DCD) has changed state. Leave most of the work to the off-level
3648 * processing routine.
3649 */
3650
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003651static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003653 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 unsigned int ioack;
3655 unsigned char misr;
3656
Jiri Slabya0564e12006-12-08 02:38:37 -08003657 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
3659 ioack = inb(ioaddr + EREG_MDACK);
3660 if (((ioack & panelp->ackmask) != 0) ||
3661 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3662 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3663 return;
3664 }
3665 portp = panelp->ports[(ioack >> 3)];
3666
3667 outb((MISR + portp->uartaddr), ioaddr);
3668 misr = inb(ioaddr + EREG_DATA);
3669 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003670 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 portp->stats.modem++;
3672 }
3673
3674 outb((EOSRR + portp->uartaddr), ioaddr);
3675 outb(0, (ioaddr + EREG_DATA));
3676}
3677
3678/*****************************************************************************/
3679/* SC26198 HARDWARE FUNCTIONS */
3680/*****************************************************************************/
3681
3682/*
3683 * These functions get/set/update the registers of the sc26198 UARTs.
3684 * Access to the sc26198 registers is via an address/data io port pair.
3685 * (Maybe should make this inline...)
3686 */
3687
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003688static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689{
3690 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003691 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692}
3693
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003694static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695{
3696 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3697 outb(value, (portp->ioaddr + XP_DATA));
3698}
3699
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003700static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701{
3702 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3703 if (inb(portp->ioaddr + XP_DATA) != value) {
3704 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003705 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003707 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708}
3709
3710/*****************************************************************************/
3711
3712/*
3713 * Functions to get and set the sc26198 global registers.
3714 */
3715
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003716static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717{
3718 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003719 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720}
3721
3722#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003723static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724{
3725 outb(regnr, (portp->ioaddr + XP_ADDR));
3726 outb(value, (portp->ioaddr + XP_DATA));
3727}
3728#endif
3729
3730/*****************************************************************************/
3731
3732/*
3733 * Inbitialize the UARTs in a panel. We don't care what sort of board
3734 * these ports are on - since the port io registers are almost
3735 * identical when dealing with ports.
3736 */
3737
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003738static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739{
3740 int chipmask, i;
3741 int nrchips, ioaddr;
3742
Jiri Slabya0564e12006-12-08 02:38:37 -08003743 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
3745 BRDENABLE(panelp->brdnr, panelp->pagenr);
3746
3747/*
3748 * Check that each chip is present and started up OK.
3749 */
3750 chipmask = 0;
3751 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3752 if (brdp->brdtype == BRD_ECHPCI)
3753 outb(panelp->pagenr, brdp->ioctrl);
3754
Jiri Slabyc62429d2006-12-08 02:39:14 -08003755 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756 ioaddr = panelp->iobase + (i * 4);
3757 outb(SCCR, (ioaddr + XP_ADDR));
3758 outb(CR_RESETALL, (ioaddr + XP_DATA));
3759 outb(TSTR, (ioaddr + XP_ADDR));
3760 if (inb(ioaddr + XP_DATA) != 0) {
3761 printk("STALLION: sc26198 not responding, "
3762 "brd=%d panel=%d chip=%d\n",
3763 panelp->brdnr, panelp->panelnr, i);
3764 continue;
3765 }
3766 chipmask |= (0x1 << i);
3767 outb(GCCR, (ioaddr + XP_ADDR));
3768 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3769 outb(WDTRCR, (ioaddr + XP_ADDR));
3770 outb(0xff, (ioaddr + XP_DATA));
3771 }
3772
3773 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003774 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775}
3776
3777/*****************************************************************************/
3778
3779/*
3780 * Initialize hardware specific port registers.
3781 */
3782
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003783static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784{
Jiri Slabya0564e12006-12-08 02:38:37 -08003785 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3786 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
Jiri Slaby615e4a72006-12-08 02:38:38 -08003788 if ((brdp == NULL) || (panelp == NULL) ||
3789 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 return;
3791
3792 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3793 portp->uartaddr = (portp->portnr & 0x07) << 4;
3794 portp->pagenr = panelp->pagenr;
3795 portp->hwid = 0x1;
3796
3797 BRDENABLE(portp->brdnr, portp->pagenr);
3798 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3799 BRDDISABLE(portp->brdnr);
3800}
3801
3802/*****************************************************************************/
3803
3804/*
3805 * Set up the sc26198 registers for a port based on the termios port
3806 * settings.
3807 */
3808
Alan Cox606d0992006-12-08 02:38:45 -08003809static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003811 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 unsigned long flags;
3813 unsigned int baudrate;
3814 unsigned char mr0, mr1, mr2, clk;
3815 unsigned char imron, imroff, iopr, ipr;
3816
3817 mr0 = 0;
3818 mr1 = 0;
3819 mr2 = 0;
3820 clk = 0;
3821 iopr = 0;
3822 imron = 0;
3823 imroff = 0;
3824
3825 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003826 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 return;
3828
3829/*
3830 * Set up the RX char ignore mask with those RX error types we
3831 * can ignore.
3832 */
3833 portp->rxignoremsk = 0;
3834 if (tiosp->c_iflag & IGNPAR)
3835 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3836 SR_RXOVERRUN);
3837 if (tiosp->c_iflag & IGNBRK)
3838 portp->rxignoremsk |= SR_RXBREAK;
3839
3840 portp->rxmarkmsk = SR_RXOVERRUN;
3841 if (tiosp->c_iflag & (INPCK | PARMRK))
3842 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3843 if (tiosp->c_iflag & BRKINT)
3844 portp->rxmarkmsk |= SR_RXBREAK;
3845
3846/*
3847 * Go through the char size, parity and stop bits and set all the
3848 * option register appropriately.
3849 */
3850 switch (tiosp->c_cflag & CSIZE) {
3851 case CS5:
3852 mr1 |= MR1_CS5;
3853 break;
3854 case CS6:
3855 mr1 |= MR1_CS6;
3856 break;
3857 case CS7:
3858 mr1 |= MR1_CS7;
3859 break;
3860 default:
3861 mr1 |= MR1_CS8;
3862 break;
3863 }
3864
3865 if (tiosp->c_cflag & CSTOPB)
3866 mr2 |= MR2_STOP2;
3867 else
3868 mr2 |= MR2_STOP1;
3869
3870 if (tiosp->c_cflag & PARENB) {
3871 if (tiosp->c_cflag & PARODD)
3872 mr1 |= (MR1_PARENB | MR1_PARODD);
3873 else
3874 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003875 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
3878 mr1 |= MR1_ERRBLOCK;
3879
3880/*
3881 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3882 * space for hardware flow control and the like. This should be set to
3883 * VMIN.
3884 */
3885 mr2 |= MR2_RXFIFOHALF;
3886
3887/*
3888 * Calculate the baud rate timers. For now we will just assume that
3889 * the input and output baud are the same. The sc26198 has a fixed
3890 * baud rate table, so only discrete baud rates possible.
3891 */
3892 baudrate = tiosp->c_cflag & CBAUD;
3893 if (baudrate & CBAUDEX) {
3894 baudrate &= ~CBAUDEX;
3895 if ((baudrate < 1) || (baudrate > 4))
3896 tiosp->c_cflag &= ~CBAUDEX;
3897 else
3898 baudrate += 15;
3899 }
3900 baudrate = stl_baudrates[baudrate];
3901 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003902 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003904 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003906 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003908 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003910 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 baudrate = (portp->baud_base / portp->custom_divisor);
3912 }
3913 if (baudrate > STL_SC26198MAXBAUD)
3914 baudrate = STL_SC26198MAXBAUD;
3915
Jiri Slabyc62429d2006-12-08 02:39:14 -08003916 if (baudrate > 0)
3917 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 if (baudrate <= sc26198_baudtable[clk])
3919 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
3921/*
3922 * Check what form of modem signaling is required and set it up.
3923 */
3924 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003925 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 } else {
3927 iopr |= IOPR_DCDCOS;
3928 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003929 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930 }
3931
3932/*
3933 * Setup sc26198 enhanced modes if we can. In particular we want to
3934 * handle as much of the flow control as possible automatically. As
3935 * well as saving a few CPU cycles it will also greatly improve flow
3936 * control reliability.
3937 */
3938 if (tiosp->c_iflag & IXON) {
3939 mr0 |= MR0_SWFTX | MR0_SWFT;
3940 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003941 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003943
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944 if (tiosp->c_iflag & IXOFF)
3945 mr0 |= MR0_SWFRX;
3946
3947 if (tiosp->c_cflag & CRTSCTS) {
3948 mr2 |= MR2_AUTOCTS;
3949 mr1 |= MR1_AUTORTS;
3950 }
3951
3952/*
3953 * All sc26198 register values calculated so go through and set
3954 * them all up.
3955 */
3956
Jiri Slabya0564e12006-12-08 02:38:37 -08003957 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003959 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3960 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3961 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3963 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964
Alan Coxb65b5b52006-06-27 02:54:05 -07003965 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 BRDENABLE(portp->brdnr, portp->pagenr);
3967 stl_sc26198setreg(portp, IMR, 0);
3968 stl_sc26198updatereg(portp, MR0, mr0);
3969 stl_sc26198updatereg(portp, MR1, mr1);
3970 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3971 stl_sc26198updatereg(portp, MR2, mr2);
3972 stl_sc26198updatereg(portp, IOPIOR,
3973 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3974
3975 if (baudrate > 0) {
3976 stl_sc26198setreg(portp, TXCSR, clk);
3977 stl_sc26198setreg(portp, RXCSR, clk);
3978 }
3979
3980 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3981 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3982
3983 ipr = stl_sc26198getreg(portp, IPR);
3984 if (ipr & IPR_DCD)
3985 portp->sigs &= ~TIOCM_CD;
3986 else
3987 portp->sigs |= TIOCM_CD;
3988
3989 portp->imr = (portp->imr & ~imroff) | imron;
3990 stl_sc26198setreg(portp, IMR, portp->imr);
3991 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003992 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993}
3994
3995/*****************************************************************************/
3996
3997/*
3998 * Set the state of the DTR and RTS signals.
3999 */
4000
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004001static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002{
4003 unsigned char iopioron, iopioroff;
4004 unsigned long flags;
4005
Jiri Slabya0564e12006-12-08 02:38:37 -08004006 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4007 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
4009 iopioron = 0;
4010 iopioroff = 0;
4011 if (dtr == 0)
4012 iopioroff |= IPR_DTR;
4013 else if (dtr > 0)
4014 iopioron |= IPR_DTR;
4015 if (rts == 0)
4016 iopioroff |= IPR_RTS;
4017 else if (rts > 0)
4018 iopioron |= IPR_RTS;
4019
Alan Coxb65b5b52006-06-27 02:54:05 -07004020 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021 BRDENABLE(portp->brdnr, portp->pagenr);
4022 stl_sc26198setreg(portp, IOPIOR,
4023 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4024 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004025 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026}
4027
4028/*****************************************************************************/
4029
4030/*
4031 * Return the state of the signals.
4032 */
4033
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004034static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035{
4036 unsigned char ipr;
4037 unsigned long flags;
4038 int sigs;
4039
Jiri Slabya0564e12006-12-08 02:38:37 -08004040 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Alan Coxb65b5b52006-06-27 02:54:05 -07004042 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043 BRDENABLE(portp->brdnr, portp->pagenr);
4044 ipr = stl_sc26198getreg(portp, IPR);
4045 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004046 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
4048 sigs = 0;
4049 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4050 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4051 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4052 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4053 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004054 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
4057/*****************************************************************************/
4058
4059/*
4060 * Enable/Disable the Transmitter and/or Receiver.
4061 */
4062
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004063static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064{
4065 unsigned char ccr;
4066 unsigned long flags;
4067
Jiri Slabya0564e12006-12-08 02:38:37 -08004068 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
4070 ccr = portp->crenable;
4071 if (tx == 0)
4072 ccr &= ~CR_TXENABLE;
4073 else if (tx > 0)
4074 ccr |= CR_TXENABLE;
4075 if (rx == 0)
4076 ccr &= ~CR_RXENABLE;
4077 else if (rx > 0)
4078 ccr |= CR_RXENABLE;
4079
Alan Coxb65b5b52006-06-27 02:54:05 -07004080 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 BRDENABLE(portp->brdnr, portp->pagenr);
4082 stl_sc26198setreg(portp, SCCR, ccr);
4083 BRDDISABLE(portp->brdnr);
4084 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004085 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086}
4087
4088/*****************************************************************************/
4089
4090/*
4091 * Start/stop the Transmitter and/or Receiver.
4092 */
4093
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004094static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095{
4096 unsigned char imr;
4097 unsigned long flags;
4098
Jiri Slabya0564e12006-12-08 02:38:37 -08004099 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
4101 imr = portp->imr;
4102 if (tx == 0)
4103 imr &= ~IR_TXRDY;
4104 else if (tx == 1)
4105 imr |= IR_TXRDY;
4106 if (rx == 0)
4107 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4108 else if (rx > 0)
4109 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4110
Alan Coxb65b5b52006-06-27 02:54:05 -07004111 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 BRDENABLE(portp->brdnr, portp->pagenr);
4113 stl_sc26198setreg(portp, IMR, imr);
4114 BRDDISABLE(portp->brdnr);
4115 portp->imr = imr;
4116 if (tx > 0)
4117 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004118 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119}
4120
4121/*****************************************************************************/
4122
4123/*
4124 * Disable all interrupts from this port.
4125 */
4126
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004127static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128{
4129 unsigned long flags;
4130
Jiri Slabya0564e12006-12-08 02:38:37 -08004131 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Alan Coxb65b5b52006-06-27 02:54:05 -07004133 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 BRDENABLE(portp->brdnr, portp->pagenr);
4135 portp->imr = 0;
4136 stl_sc26198setreg(portp, IMR, 0);
4137 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004138 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139}
4140
4141/*****************************************************************************/
4142
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004143static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144{
4145 unsigned long flags;
4146
Jiri Slabya0564e12006-12-08 02:38:37 -08004147 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Alan Coxb65b5b52006-06-27 02:54:05 -07004149 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 BRDENABLE(portp->brdnr, portp->pagenr);
4151 if (len == 1) {
4152 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4153 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004154 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004156
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004158 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159}
4160
4161/*****************************************************************************/
4162
4163/*
4164 * Take flow control actions...
4165 */
4166
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004167static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168{
4169 struct tty_struct *tty;
4170 unsigned long flags;
4171 unsigned char mr0;
4172
Jiri Slabya0564e12006-12-08 02:38:37 -08004173 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Jiri Slaby615e4a72006-12-08 02:38:38 -08004175 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004177 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004178 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179 return;
4180
Alan Coxb65b5b52006-06-27 02:54:05 -07004181 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 BRDENABLE(portp->brdnr, portp->pagenr);
4183
4184 if (state) {
4185 if (tty->termios->c_iflag & IXOFF) {
4186 mr0 = stl_sc26198getreg(portp, MR0);
4187 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4188 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4189 mr0 |= MR0_SWFRX;
4190 portp->stats.rxxon++;
4191 stl_sc26198wait(portp);
4192 stl_sc26198setreg(portp, MR0, mr0);
4193 }
4194/*
4195 * Question: should we return RTS to what it was before? It may
4196 * have been set by an ioctl... Suppose not, since if you have
4197 * hardware flow control set then it is pretty silly to go and
4198 * set the RTS line by hand.
4199 */
4200 if (tty->termios->c_cflag & CRTSCTS) {
4201 stl_sc26198setreg(portp, MR1,
4202 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4203 stl_sc26198setreg(portp, IOPIOR,
4204 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4205 portp->stats.rxrtson++;
4206 }
4207 } else {
4208 if (tty->termios->c_iflag & IXOFF) {
4209 mr0 = stl_sc26198getreg(portp, MR0);
4210 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4211 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4212 mr0 &= ~MR0_SWFRX;
4213 portp->stats.rxxoff++;
4214 stl_sc26198wait(portp);
4215 stl_sc26198setreg(portp, MR0, mr0);
4216 }
4217 if (tty->termios->c_cflag & CRTSCTS) {
4218 stl_sc26198setreg(portp, MR1,
4219 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4220 stl_sc26198setreg(portp, IOPIOR,
4221 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4222 portp->stats.rxrtsoff++;
4223 }
4224 }
4225
4226 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004227 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228}
4229
4230/*****************************************************************************/
4231
4232/*
4233 * Send a flow control character.
4234 */
4235
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004236static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237{
4238 struct tty_struct *tty;
4239 unsigned long flags;
4240 unsigned char mr0;
4241
Jiri Slabya0564e12006-12-08 02:38:37 -08004242 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243
Jiri Slaby615e4a72006-12-08 02:38:38 -08004244 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 return;
Alan Coxf8ae4762008-07-16 21:56:37 +01004246 tty = portp->port.tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004247 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 return;
4249
Alan Coxb65b5b52006-06-27 02:54:05 -07004250 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 BRDENABLE(portp->brdnr, portp->pagenr);
4252 if (state) {
4253 mr0 = stl_sc26198getreg(portp, MR0);
4254 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4255 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4256 mr0 |= MR0_SWFRX;
4257 portp->stats.rxxon++;
4258 stl_sc26198wait(portp);
4259 stl_sc26198setreg(portp, MR0, mr0);
4260 } else {
4261 mr0 = stl_sc26198getreg(portp, MR0);
4262 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4263 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4264 mr0 &= ~MR0_SWFRX;
4265 portp->stats.rxxoff++;
4266 stl_sc26198wait(portp);
4267 stl_sc26198setreg(portp, MR0, mr0);
4268 }
4269 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004270 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
4273/*****************************************************************************/
4274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004275static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276{
4277 unsigned long flags;
4278
Jiri Slabya0564e12006-12-08 02:38:37 -08004279 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
Jiri Slaby615e4a72006-12-08 02:38:38 -08004281 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 return;
4283
Alan Coxb65b5b52006-06-27 02:54:05 -07004284 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 BRDENABLE(portp->brdnr, portp->pagenr);
4286 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4287 stl_sc26198setreg(portp, SCCR, portp->crenable);
4288 BRDDISABLE(portp->brdnr);
4289 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004290 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291}
4292
4293/*****************************************************************************/
4294
4295/*
4296 * Return the current state of data flow on this port. This is only
4297 * really interresting when determining if data has fully completed
4298 * transmission or not... The sc26198 interrupt scheme cannot
4299 * determine when all data has actually drained, so we need to
4300 * check the port statusy register to be sure.
4301 */
4302
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004303static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304{
4305 unsigned long flags;
4306 unsigned char sr;
4307
Jiri Slabya0564e12006-12-08 02:38:37 -08004308 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Jiri Slaby615e4a72006-12-08 02:38:38 -08004310 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004311 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004313 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
Alan Coxb65b5b52006-06-27 02:54:05 -07004315 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316 BRDENABLE(portp->brdnr, portp->pagenr);
4317 sr = stl_sc26198getreg(portp, SR);
4318 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004319 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Jesper Juhl014c2542006-01-15 02:37:08 +01004321 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
4324/*****************************************************************************/
4325
4326/*
4327 * Delay for a small amount of time, to give the sc26198 a chance
4328 * to process a command...
4329 */
4330
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004331static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332{
4333 int i;
4334
Jiri Slabya0564e12006-12-08 02:38:37 -08004335 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Jiri Slaby615e4a72006-12-08 02:38:38 -08004337 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 return;
4339
Jiri Slabyc62429d2006-12-08 02:39:14 -08004340 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341 stl_sc26198getglobreg(portp, TSTR);
4342}
4343
4344/*****************************************************************************/
4345
4346/*
4347 * If we are TX flow controlled and in IXANY mode then we may
4348 * need to unflow control here. We gotta do this because of the
4349 * automatic flow control modes of the sc26198.
4350 */
4351
Jiri Slaby60be4812006-12-08 02:38:40 -08004352static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353{
4354 unsigned char mr0;
4355
4356 mr0 = stl_sc26198getreg(portp, MR0);
4357 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4358 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4359 stl_sc26198wait(portp);
4360 stl_sc26198setreg(portp, MR0, mr0);
4361 clear_bit(ASYI_TXFLOWED, &portp->istate);
4362}
4363
4364/*****************************************************************************/
4365
4366/*
4367 * Interrupt service routine for sc26198 panels.
4368 */
4369
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004370static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004372 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 unsigned int iack;
4374
Alan Coxb65b5b52006-06-27 02:54:05 -07004375 spin_lock(&brd_lock);
4376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377/*
4378 * Work around bug in sc26198 chip... Cannot have A6 address
4379 * line of UART high, else iack will be returned as 0.
4380 */
4381 outb(0, (iobase + 1));
4382
4383 iack = inb(iobase + XP_IACK);
4384 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4385
4386 if (iack & IVR_RXDATA)
4387 stl_sc26198rxisr(portp, iack);
4388 else if (iack & IVR_TXDATA)
4389 stl_sc26198txisr(portp);
4390 else
4391 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004392
4393 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394}
4395
4396/*****************************************************************************/
4397
4398/*
4399 * Transmit interrupt handler. This has gotta be fast! Handling TX
4400 * chars is pretty simple, stuff as many as possible from the TX buffer
4401 * into the sc26198 FIFO.
4402 * In practice it is possible that interrupts are enabled but that the
4403 * port has been hung up. Need to handle not having any TX buffer here,
4404 * this is done by using the side effect that head and tail will also
4405 * be NULL if the buffer has been freed.
4406 */
4407
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004408static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409{
4410 unsigned int ioaddr;
4411 unsigned char mr0;
4412 int len, stlen;
4413 char *head, *tail;
4414
Jiri Slabya0564e12006-12-08 02:38:37 -08004415 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
4417 ioaddr = portp->ioaddr;
4418 head = portp->tx.head;
4419 tail = portp->tx.tail;
4420 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4421 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4422 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4423 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxf8ae4762008-07-16 21:56:37 +01004424 if (portp->port.tty)
4425 tty_wakeup(portp->port.tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426 }
4427
4428 if (len == 0) {
4429 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4430 mr0 = inb(ioaddr + XP_DATA);
4431 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4432 portp->imr &= ~IR_TXRDY;
4433 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4434 outb(portp->imr, (ioaddr + XP_DATA));
4435 clear_bit(ASYI_TXBUSY, &portp->istate);
4436 } else {
4437 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4438 outb(mr0, (ioaddr + XP_DATA));
4439 }
4440 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004441 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004443 stlen = min_t(unsigned int, len,
4444 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 outb(GTXFIFO, (ioaddr + XP_ADDR));
4446 outsb((ioaddr + XP_DATA), tail, stlen);
4447 len -= stlen;
4448 tail += stlen;
4449 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4450 tail = portp->tx.buf;
4451 if (len > 0) {
4452 outsb((ioaddr + XP_DATA), tail, len);
4453 tail += len;
4454 }
4455 portp->tx.tail = tail;
4456 }
4457}
4458
4459/*****************************************************************************/
4460
4461/*
4462 * Receive character interrupt handler. Determine if we have good chars
4463 * or bad chars and then process appropriately. Good chars are easy
4464 * just shove the lot into the RX buffer and set all status byte to 0.
4465 * If a bad RX char then process as required. This routine needs to be
4466 * fast! In practice it is possible that we get an interrupt on a port
4467 * that is closed. This can happen on hangups - since they completely
4468 * shutdown a port not in user context. Need to handle this case.
4469 */
4470
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004471static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472{
4473 struct tty_struct *tty;
4474 unsigned int len, buflen, ioaddr;
4475
Jiri Slabya0564e12006-12-08 02:38:37 -08004476 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
Alan Coxf8ae4762008-07-16 21:56:37 +01004478 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479 ioaddr = portp->ioaddr;
4480 outb(GIBCR, (ioaddr + XP_ADDR));
4481 len = inb(ioaddr + XP_DATA) + 1;
4482
4483 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004484 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004485 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 outb(GRXFIFO, (ioaddr + XP_ADDR));
4487 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4488 portp->stats.rxlost += len;
4489 portp->stats.rxtotal += len;
4490 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004491 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004493 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004495 tty_prepare_flip_string(tty, &ptr, len);
4496 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497 tty_schedule_flip(tty);
4498 portp->stats.rxtotal += len;
4499 }
4500 }
4501 } else {
4502 stl_sc26198rxbadchars(portp);
4503 }
4504
4505/*
4506 * If we are TX flow controlled and in IXANY mode then we may need
4507 * to unflow control here. We gotta do this because of the automatic
4508 * flow control modes of the sc26198.
4509 */
4510 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004511 if ((tty != NULL) &&
4512 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 (tty->termios->c_iflag & IXANY)) {
4514 stl_sc26198txunflow(portp, tty);
4515 }
4516 }
4517}
4518
4519/*****************************************************************************/
4520
4521/*
4522 * Process an RX bad character.
4523 */
4524
Jiri Slaby60be4812006-12-08 02:38:40 -08004525static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526{
4527 struct tty_struct *tty;
4528 unsigned int ioaddr;
4529
Alan Coxf8ae4762008-07-16 21:56:37 +01004530 tty = portp->port.tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 ioaddr = portp->ioaddr;
4532
4533 if (status & SR_RXPARITY)
4534 portp->stats.rxparity++;
4535 if (status & SR_RXFRAMING)
4536 portp->stats.rxframing++;
4537 if (status & SR_RXOVERRUN)
4538 portp->stats.rxoverrun++;
4539 if (status & SR_RXBREAK)
4540 portp->stats.rxbreaks++;
4541
Jiri Slaby615e4a72006-12-08 02:38:38 -08004542 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 ((portp->rxignoremsk & status) == 0)) {
4544 if (portp->rxmarkmsk & status) {
4545 if (status & SR_RXBREAK) {
4546 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004547 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 do_SAK(tty);
4549 BRDENABLE(portp->brdnr, portp->pagenr);
4550 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004551 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004553 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004555 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004557 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004559 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561
Alan Cox33f0f882006-01-09 20:54:13 -08004562 tty_insert_flip_char(tty, ch, status);
4563 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
4565 if (status == 0)
4566 portp->stats.rxtotal++;
4567 }
4568}
4569
4570/*****************************************************************************/
4571
4572/*
4573 * Process all characters in the RX FIFO of the UART. Check all char
4574 * status bytes as well, and process as required. We need to check
4575 * all bytes in the FIFO, in case some more enter the FIFO while we
4576 * are here. To get the exact character error type we need to switch
4577 * into CHAR error mode (that is why we need to make sure we empty
4578 * the FIFO).
4579 */
4580
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004581static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582{
4583 unsigned char status, mr1;
4584 char ch;
4585
4586/*
4587 * To get the precise error type for each character we must switch
4588 * back into CHAR error mode.
4589 */
4590 mr1 = stl_sc26198getreg(portp, MR1);
4591 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4592
4593 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4594 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4595 ch = stl_sc26198getreg(portp, RXFIFO);
4596 stl_sc26198rxbadch(portp, status, ch);
4597 }
4598
4599/*
4600 * To get correct interrupt class we must switch back into BLOCK
4601 * error mode.
4602 */
4603 stl_sc26198setreg(portp, MR1, mr1);
4604}
4605
4606/*****************************************************************************/
4607
4608/*
4609 * Other interrupt handler. This includes modem signals, flow
4610 * control actions, etc. Most stuff is left to off-level interrupt
4611 * processing time.
4612 */
4613
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004614static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615{
4616 unsigned char cir, ipr, xisr;
4617
Jiri Slabya0564e12006-12-08 02:38:37 -08004618 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619
4620 cir = stl_sc26198getglobreg(portp, CIR);
4621
4622 switch (cir & CIR_SUBTYPEMASK) {
4623 case CIR_SUBCOS:
4624 ipr = stl_sc26198getreg(portp, IPR);
4625 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004626 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 portp->stats.modem++;
4628 }
4629 break;
4630 case CIR_SUBXONXOFF:
4631 xisr = stl_sc26198getreg(portp, XISR);
4632 if (xisr & XISR_RXXONGOT) {
4633 set_bit(ASYI_TXFLOWED, &portp->istate);
4634 portp->stats.txxoff++;
4635 }
4636 if (xisr & XISR_RXXOFFGOT) {
4637 clear_bit(ASYI_TXFLOWED, &portp->istate);
4638 portp->stats.txxon++;
4639 }
4640 break;
4641 case CIR_SUBBREAK:
4642 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4643 stl_sc26198rxbadchars(portp);
4644 break;
4645 default:
4646 break;
4647 }
4648}
4649
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004650static void stl_free_isabrds(void)
4651{
4652 struct stlbrd *brdp;
4653 unsigned int i;
4654
4655 for (i = 0; i < stl_nrbrds; i++) {
4656 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4657 continue;
4658
4659 free_irq(brdp->irq, brdp);
4660
4661 stl_cleanup_panels(brdp);
4662
4663 release_region(brdp->ioaddr1, brdp->iosize1);
4664 if (brdp->iosize2 > 0)
4665 release_region(brdp->ioaddr2, brdp->iosize2);
4666
4667 kfree(brdp);
4668 stl_brds[i] = NULL;
4669 }
4670}
4671
Jiri Slaby23b85a12006-12-08 02:38:40 -08004672/*
4673 * Loadable module initialization stuff.
4674 */
4675static int __init stallion_module_init(void)
4676{
Jiri Slaby843b5682006-12-08 02:39:12 -08004677 struct stlbrd *brdp;
4678 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004679 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004680 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004681
4682 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4683
4684 spin_lock_init(&stallion_lock);
4685 spin_lock_init(&brd_lock);
4686
Jiri Slabye4151092007-06-08 13:46:52 -07004687 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4688 if (!stl_serial) {
4689 retval = -ENOMEM;
4690 goto err;
4691 }
4692
4693 stl_serial->owner = THIS_MODULE;
4694 stl_serial->driver_name = stl_drvname;
4695 stl_serial->name = "ttyE";
4696 stl_serial->major = STL_SERIALMAJOR;
4697 stl_serial->minor_start = 0;
4698 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4699 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4700 stl_serial->init_termios = stl_deftermios;
4701 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4702 tty_set_operations(stl_serial, &stl_ops);
4703
4704 retval = tty_register_driver(stl_serial);
4705 if (retval) {
4706 printk("STALLION: failed to register serial driver\n");
4707 goto err_frtty;
4708 }
4709
Jiri Slaby843b5682006-12-08 02:39:12 -08004710/*
4711 * Find any dynamically supported boards. That is via module load
4712 * line options.
4713 */
4714 for (i = stl_nrbrds; i < stl_nargs; i++) {
4715 memset(&conf, 0, sizeof(conf));
4716 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4717 continue;
4718 if ((brdp = stl_allocbrd()) == NULL)
4719 continue;
4720 brdp->brdnr = i;
4721 brdp->brdtype = conf.brdtype;
4722 brdp->ioaddr1 = conf.ioaddr1;
4723 brdp->ioaddr2 = conf.ioaddr2;
4724 brdp->irq = conf.irq;
4725 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004726 stl_brds[brdp->brdnr] = brdp;
4727 if (stl_brdinit(brdp)) {
4728 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004729 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004730 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004731 for (j = 0; j < brdp->nrports; j++)
4732 tty_register_device(stl_serial,
4733 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004734 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004735 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004736 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004737
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004738 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004739 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004740 if (retval && stl_nrbrds == 0) {
4741 printk(KERN_ERR "STALLION: can't register pci driver\n");
4742 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004743 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004744
4745/*
4746 * Set up a character driver for per board stuff. This is mainly used
4747 * to do stats ioctls on the ports.
4748 */
4749 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4750 printk("STALLION: failed to register serial board device\n");
4751
4752 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004753 if (IS_ERR(stallion_class))
4754 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004755 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004756 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4757 "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004758
Jiri Slaby23b85a12006-12-08 02:38:40 -08004759 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004760err_unrtty:
4761 tty_unregister_driver(stl_serial);
4762err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004763 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004764err:
4765 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004766}
4767
4768static void __exit stallion_module_exit(void)
4769{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004770 struct stlbrd *brdp;
4771 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004772
4773 pr_debug("cleanup_module()\n");
4774
4775 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4776 stl_drvversion);
4777
4778/*
4779 * Free up all allocated resources used by the ports. This includes
4780 * memory and interrupts. As part of this process we will also do
4781 * a hangup on every open port - to try to flush out any processes
4782 * hanging onto ports.
4783 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004784 for (i = 0; i < stl_nrbrds; i++) {
4785 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4786 continue;
4787 for (j = 0; j < brdp->nrports; j++)
4788 tty_unregister_device(stl_serial,
4789 brdp->brdnr * STL_MAXPORTS + j);
4790 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004791
Jiri Slaby23b85a12006-12-08 02:38:40 -08004792 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004793 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004794 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004795 class_destroy(stallion_class);
4796
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004797 pci_unregister_driver(&stl_pcidriver);
4798
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004799 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004800
4801 tty_unregister_driver(stl_serial);
4802 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004803}
4804
4805module_init(stallion_module_init);
4806module_exit(stallion_module_exit);
4807
4808MODULE_AUTHOR("Greg Ungerer");
4809MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4810MODULE_LICENSE("GPL");