blob: b108ac6e3d83a18c23827cc6cf7b6e27fbbb67a2 [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>
44
45#include <asm/io.h>
46#include <asm/uaccess.h>
47
48#ifdef CONFIG_PCI
49#include <linux/pci.h>
50#endif
51
52/*****************************************************************************/
53
54/*
55 * Define different board types. Use the standard Stallion "assigned"
56 * board numbers. Boards supported in this driver are abbreviated as
57 * EIO = EasyIO and ECH = EasyConnection 8/32.
58 */
59#define BRD_EASYIO 20
60#define BRD_ECH 21
61#define BRD_ECHMC 22
62#define BRD_ECHPCI 26
63#define BRD_ECH64PCI 27
64#define BRD_EASYIOPCI 28
65
66/*
67 * Define a configuration structure to hold the board configuration.
68 * Need to set this up in the code (for now) with the boards that are
69 * to be configured into the system. This is what needs to be modified
70 * when adding/removing/modifying boards. Each line entry in the
71 * stl_brdconf[] array is a board. Each line contains io/irq/memory
72 * ranges for that board (as well as what type of board it is).
73 * Some examples:
74 * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
75 * This line would configure an EasyIO board (4 or 8, no difference),
76 * at io address 2a0 and irq 10.
77 * Another example:
78 * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 },
79 * This line will configure an EasyConnection 8/32 board at primary io
80 * address 2a8, secondary io address 280 and irq 12.
81 * Enter as many lines into this array as you want (only the first 4
82 * will actually be used!). Any combination of EasyIO and EasyConnection
83 * boards can be specified. EasyConnection 8/32 boards can share their
84 * secondary io addresses between each other.
85 *
86 * NOTE: there is no need to put any entries in this table for PCI
87 * boards. They will be found automatically by the driver - provided
88 * PCI BIOS32 support is compiled into the kernel.
89 */
90
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080091static struct stlconf {
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 int brdtype;
93 int ioaddr1;
94 int ioaddr2;
95 unsigned long memaddr;
96 int irq;
97 int irqtype;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -080098} stl_brdconf[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
100};
101
Tobias Klauserfe971072006-01-09 20:54:02 -0800102static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104/*****************************************************************************/
105
106/*
107 * Define some important driver characteristics. Device major numbers
108 * allocated as per Linux Device Registry.
109 */
110#ifndef STL_SIOMEMMAJOR
111#define STL_SIOMEMMAJOR 28
112#endif
113#ifndef STL_SERIALMAJOR
114#define STL_SERIALMAJOR 24
115#endif
116#ifndef STL_CALLOUTMAJOR
117#define STL_CALLOUTMAJOR 25
118#endif
119
120/*
121 * Set the TX buffer size. Bigger is better, but we don't want
122 * to chew too much memory with buffers!
123 */
124#define STL_TXBUFLOW 512
125#define STL_TXBUFSIZE 4096
126
127/*****************************************************************************/
128
129/*
130 * Define our local driver identity first. Set up stuff to deal with
131 * all the local structures required by a serial tty driver.
132 */
133static char *stl_drvtitle = "Stallion Multiport Serial Driver";
134static char *stl_drvname = "stallion";
135static char *stl_drvversion = "5.6.0";
136
137static struct tty_driver *stl_serial;
138
139/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 * Define a local default termios struct. All ports will be created
141 * with this termios initially. Basically all it defines is a raw port
142 * at 9600, 8 data bits, 1 stop bit.
143 */
144static struct termios stl_deftermios = {
145 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
146 .c_cc = INIT_C_CC,
147};
148
149/*
150 * Define global stats structures. Not used often, and can be
151 * re-used for each stats call.
152 */
153static comstats_t stl_comstats;
154static combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800155static struct stlbrd stl_dummybrd;
156static struct stlport stl_dummyport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
158/*
159 * Define global place to put buffer overflow characters.
160 */
161static char stl_unwanted[SC26198_RXFIFOSIZE];
162
163/*****************************************************************************/
164
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800165static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167/*
168 * Per board state flags. Used with the state field of the board struct.
169 * Not really much here!
170 */
171#define BRD_FOUND 0x1
172
173/*
174 * Define the port structure istate flags. These set of flags are
175 * modified at interrupt time - so setting and reseting them needs
176 * to be atomic. Use the bit clear/setting routines for this.
177 */
178#define ASYI_TXBUSY 1
179#define ASYI_TXLOW 2
180#define ASYI_DCDCHANGE 3
181#define ASYI_TXFLOWED 4
182
183/*
184 * Define an array of board names as printable strings. Handy for
185 * referencing boards when printing trace and stuff.
186 */
187static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800188 NULL,
189 NULL,
190 NULL,
191 NULL,
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 NULL,
197 NULL,
198 NULL,
199 NULL,
200 NULL,
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 NULL,
206 NULL,
207 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 "EasyIO",
209 "EC8/32-AT",
210 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800211 NULL,
212 NULL,
213 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 "EC8/32-PCI",
215 "EC8/64-PCI",
216 "EasyIO-PCI",
217};
218
219/*****************************************************************************/
220
221/*
222 * Define some string labels for arguments passed from the module
223 * load line. These allow for easy board definitions, and easy
224 * modification of the io, memory and irq resoucres.
225 */
226static int stl_nargs = 0;
227static char *board0[4];
228static char *board1[4];
229static char *board2[4];
230static char *board3[4];
231
232static char **stl_brdsp[] = {
233 (char **) &board0,
234 (char **) &board1,
235 (char **) &board2,
236 (char **) &board3
237};
238
239/*
240 * Define a set of common board names, and types. This is used to
241 * parse any module arguments.
242 */
243
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800244static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 char *name;
246 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800247} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 { "easyio", BRD_EASYIO },
249 { "eio", BRD_EASYIO },
250 { "20", BRD_EASYIO },
251 { "ec8/32", BRD_ECH },
252 { "ec8/32-at", BRD_ECH },
253 { "ec8/32-isa", BRD_ECH },
254 { "ech", BRD_ECH },
255 { "echat", BRD_ECH },
256 { "21", BRD_ECH },
257 { "ec8/32-mc", BRD_ECHMC },
258 { "ec8/32-mca", BRD_ECHMC },
259 { "echmc", BRD_ECHMC },
260 { "echmca", BRD_ECHMC },
261 { "22", BRD_ECHMC },
262 { "ec8/32-pc", BRD_ECHPCI },
263 { "ec8/32-pci", BRD_ECHPCI },
264 { "26", BRD_ECHPCI },
265 { "ec8/64-pc", BRD_ECH64PCI },
266 { "ec8/64-pci", BRD_ECH64PCI },
267 { "ech-pci", BRD_ECH64PCI },
268 { "echpci", BRD_ECH64PCI },
269 { "echpc", BRD_ECH64PCI },
270 { "27", BRD_ECH64PCI },
271 { "easyio-pc", BRD_EASYIOPCI },
272 { "easyio-pci", BRD_EASYIOPCI },
273 { "eio-pci", BRD_EASYIOPCI },
274 { "eiopci", BRD_EASYIOPCI },
275 { "28", BRD_EASYIOPCI },
276};
277
278/*
279 * Define the module agruments.
280 */
281MODULE_AUTHOR("Greg Ungerer");
282MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
283MODULE_LICENSE("GPL");
284
285module_param_array(board0, charp, &stl_nargs, 0);
286MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
287module_param_array(board1, charp, &stl_nargs, 0);
288MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
289module_param_array(board2, charp, &stl_nargs, 0);
290MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
291module_param_array(board3, charp, &stl_nargs, 0);
292MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
293
294/*****************************************************************************/
295
296/*
297 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
298 * to the directly accessible io ports of these boards (not the uarts -
299 * they are in cd1400.h and sc26198.h).
300 */
301#define EIO_8PORTRS 0x04
302#define EIO_4PORTRS 0x05
303#define EIO_8PORTDI 0x00
304#define EIO_8PORTM 0x06
305#define EIO_MK3 0x03
306#define EIO_IDBITMASK 0x07
307
308#define EIO_BRDMASK 0xf0
309#define ID_BRD4 0x10
310#define ID_BRD8 0x20
311#define ID_BRD16 0x30
312
313#define EIO_INTRPEND 0x08
314#define EIO_INTEDGE 0x00
315#define EIO_INTLEVEL 0x08
316#define EIO_0WS 0x10
317
318#define ECH_ID 0xa0
319#define ECH_IDBITMASK 0xe0
320#define ECH_BRDENABLE 0x08
321#define ECH_BRDDISABLE 0x00
322#define ECH_INTENABLE 0x01
323#define ECH_INTDISABLE 0x00
324#define ECH_INTLEVEL 0x02
325#define ECH_INTEDGE 0x00
326#define ECH_INTRPEND 0x01
327#define ECH_BRDRESET 0x01
328
329#define ECHMC_INTENABLE 0x01
330#define ECHMC_BRDRESET 0x02
331
332#define ECH_PNLSTATUS 2
333#define ECH_PNL16PORT 0x20
334#define ECH_PNLIDMASK 0x07
335#define ECH_PNLXPID 0x40
336#define ECH_PNLINTRPEND 0x80
337
338#define ECH_ADDR2MASK 0x1e0
339
340/*
341 * Define the vector mapping bits for the programmable interrupt board
342 * hardware. These bits encode the interrupt for the board to use - it
343 * is software selectable (except the EIO-8M).
344 */
345static unsigned char stl_vecmap[] = {
346 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
347 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
348};
349
350/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700351 * Lock ordering is that you may not take stallion_lock holding
352 * brd_lock.
353 */
354
355static spinlock_t brd_lock; /* Guard the board mapping */
356static spinlock_t stallion_lock; /* Guard the tty driver */
357
358/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 * Set up enable and disable macros for the ECH boards. They require
360 * the secondary io address space to be activated and deactivated.
361 * This way all ECH boards can share their secondary io region.
362 * If this is an ECH-PCI board then also need to set the page pointer
363 * to point to the correct page.
364 */
365#define BRDENABLE(brdnr,pagenr) \
366 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
367 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
368 stl_brds[(brdnr)]->ioctrl); \
369 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
370 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
371
372#define BRDDISABLE(brdnr) \
373 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
374 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
375 stl_brds[(brdnr)]->ioctrl);
376
377#define STL_CD1400MAXBAUD 230400
378#define STL_SC26198MAXBAUD 460800
379
380#define STL_BAUDBASE 115200
381#define STL_CLOSEDELAY (5 * HZ / 10)
382
383/*****************************************************************************/
384
385#ifdef CONFIG_PCI
386
387/*
388 * Define the Stallion PCI vendor and device IDs.
389 */
390#ifndef PCI_VENDOR_ID_STALLION
391#define PCI_VENDOR_ID_STALLION 0x124d
392#endif
393#ifndef PCI_DEVICE_ID_ECHPCI832
394#define PCI_DEVICE_ID_ECHPCI832 0x0000
395#endif
396#ifndef PCI_DEVICE_ID_ECHPCI864
397#define PCI_DEVICE_ID_ECHPCI864 0x0002
398#endif
399#ifndef PCI_DEVICE_ID_EIOPCI
400#define PCI_DEVICE_ID_EIOPCI 0x0003
401#endif
402
403/*
404 * Define structure to hold all Stallion PCI boards.
405 */
406typedef struct stlpcibrd {
407 unsigned short vendid;
408 unsigned short devid;
409 int brdtype;
410} stlpcibrd_t;
411
412static stlpcibrd_t stl_pcibrds[] = {
413 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI },
414 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI },
415 { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI },
416 { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
417};
418
Tobias Klauserfe971072006-01-09 20:54:02 -0800419static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
421#endif
422
423/*****************************************************************************/
424
425/*
426 * Define macros to extract a brd/port number from a minor number.
427 */
428#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
429#define MINOR2PORT(min) ((min) & 0x3f)
430
431/*
432 * Define a baud rate table that converts termios baud rate selector
433 * into the actual baud rate value. All baud rate calculations are
434 * based on the actual baud rate required.
435 */
436static unsigned int stl_baudrates[] = {
437 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
438 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
439};
440
441/*
442 * Define some handy local macros...
443 */
444#undef MIN
445#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
446
447#undef TOLOWER
448#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))
449
450/*****************************************************************************/
451
452/*
453 * Declare all those functions in this driver!
454 */
455
456static void stl_argbrds(void);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800457static int stl_parsebrd(struct stlconf *confp, char **argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
459static unsigned long stl_atol(char *str);
460
Adrian Bunk408b6642005-05-01 08:59:29 -0700461static int stl_init(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462static int stl_open(struct tty_struct *tty, struct file *filp);
463static void stl_close(struct tty_struct *tty, struct file *filp);
464static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
465static void stl_putchar(struct tty_struct *tty, unsigned char ch);
466static void stl_flushchars(struct tty_struct *tty);
467static int stl_writeroom(struct tty_struct *tty);
468static int stl_charsinbuffer(struct tty_struct *tty);
469static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
470static void stl_settermios(struct tty_struct *tty, struct termios *old);
471static void stl_throttle(struct tty_struct *tty);
472static void stl_unthrottle(struct tty_struct *tty);
473static void stl_stop(struct tty_struct *tty);
474static void stl_start(struct tty_struct *tty);
475static void stl_flushbuffer(struct tty_struct *tty);
476static void stl_breakctl(struct tty_struct *tty, int state);
477static void stl_waituntilsent(struct tty_struct *tty, int timeout);
478static void stl_sendxchar(struct tty_struct *tty, char ch);
479static void stl_hangup(struct tty_struct *tty);
480static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800481static int stl_portinfo(struct stlport *portp, int portnr, char *pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data);
483
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800484static int stl_brdinit(struct stlbrd *brdp);
485static int stl_initports(struct stlbrd *brdp, struct stlpanel *panelp);
486static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp);
487static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488static int stl_getbrdstats(combrd_t __user *bp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800489static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
490static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
491static int stl_getportstruct(struct stlport __user *arg);
492static int stl_getbrdstruct(struct stlbrd __user *arg);
493static int stl_waitcarrier(struct stlport *portp, struct file *filp);
494static int stl_eiointr(struct stlbrd *brdp);
495static int stl_echatintr(struct stlbrd *brdp);
496static int stl_echmcaintr(struct stlbrd *brdp);
497static int stl_echpciintr(struct stlbrd *brdp);
498static int stl_echpci64intr(struct stlbrd *brdp);
Al Viro3e577a82006-12-06 18:41:45 +0000499static void stl_offintr(struct work_struct *);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800500static struct stlbrd *stl_allocbrd(void);
501static struct stlport *stl_getport(int brdnr, int panelnr, int portnr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503static inline int stl_initbrds(void);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800504static inline int stl_initeio(struct stlbrd *brdp);
505static inline int stl_initech(struct stlbrd *brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506static inline int stl_getbrdnr(void);
507
508#ifdef CONFIG_PCI
509static inline int stl_findpcibrds(void);
510static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp);
511#endif
512
513/*
514 * CD1400 uart specific handling functions.
515 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800516static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
517static int stl_cd1400getreg(struct stlport *portp, int regnr);
518static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
519static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
520static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
521static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp);
522static int stl_cd1400getsignals(struct stlport *portp);
523static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
524static void stl_cd1400ccrwait(struct stlport *portp);
525static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
526static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
527static void stl_cd1400disableintrs(struct stlport *portp);
528static void stl_cd1400sendbreak(struct stlport *portp, int len);
529static void stl_cd1400flowctrl(struct stlport *portp, int state);
530static void stl_cd1400sendflow(struct stlport *portp, int state);
531static void stl_cd1400flush(struct stlport *portp);
532static int stl_cd1400datastate(struct stlport *portp);
533static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
534static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
535static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
536static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
537static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800539static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
541/*
542 * SC26198 uart specific handling functions.
543 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800544static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
545static int stl_sc26198getreg(struct stlport *portp, int regnr);
546static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
547static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
548static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
549static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
550static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp);
551static int stl_sc26198getsignals(struct stlport *portp);
552static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
553static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
554static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
555static void stl_sc26198disableintrs(struct stlport *portp);
556static void stl_sc26198sendbreak(struct stlport *portp, int len);
557static void stl_sc26198flowctrl(struct stlport *portp, int state);
558static void stl_sc26198sendflow(struct stlport *portp, int state);
559static void stl_sc26198flush(struct stlport *portp);
560static int stl_sc26198datastate(struct stlport *portp);
561static void stl_sc26198wait(struct stlport *portp);
562static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
563static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
564static void stl_sc26198txisr(struct stlport *port);
565static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
566static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
567static void stl_sc26198rxbadchars(struct stlport *portp);
568static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570/*****************************************************************************/
571
572/*
573 * Generic UART support structure.
574 */
575typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800576 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
577 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
578 void (*setport)(struct stlport *portp, struct termios *tiosp);
579 int (*getsignals)(struct stlport *portp);
580 void (*setsignals)(struct stlport *portp, int dtr, int rts);
581 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
582 void (*startrxtx)(struct stlport *portp, int rx, int tx);
583 void (*disableintrs)(struct stlport *portp);
584 void (*sendbreak)(struct stlport *portp, int len);
585 void (*flowctrl)(struct stlport *portp, int state);
586 void (*sendflow)(struct stlport *portp, int state);
587 void (*flush)(struct stlport *portp);
588 int (*datastate)(struct stlport *portp);
589 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590} uart_t;
591
592/*
593 * Define some macros to make calling these functions nice and clean.
594 */
595#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
596#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
597#define stl_setport (* ((uart_t *) portp->uartp)->setport)
598#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
599#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
600#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
601#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
602#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
603#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
604#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
605#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
606#define stl_flush (* ((uart_t *) portp->uartp)->flush)
607#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
608
609/*****************************************************************************/
610
611/*
612 * CD1400 UART specific data initialization.
613 */
614static uart_t stl_cd1400uart = {
615 stl_cd1400panelinit,
616 stl_cd1400portinit,
617 stl_cd1400setport,
618 stl_cd1400getsignals,
619 stl_cd1400setsignals,
620 stl_cd1400enablerxtx,
621 stl_cd1400startrxtx,
622 stl_cd1400disableintrs,
623 stl_cd1400sendbreak,
624 stl_cd1400flowctrl,
625 stl_cd1400sendflow,
626 stl_cd1400flush,
627 stl_cd1400datastate,
628 stl_cd1400eiointr
629};
630
631/*
632 * Define the offsets within the register bank of a cd1400 based panel.
633 * These io address offsets are common to the EasyIO board as well.
634 */
635#define EREG_ADDR 0
636#define EREG_DATA 4
637#define EREG_RXACK 5
638#define EREG_TXACK 6
639#define EREG_MDACK 7
640
641#define EREG_BANKSIZE 8
642
643#define CD1400_CLK 25000000
644#define CD1400_CLK8M 20000000
645
646/*
647 * Define the cd1400 baud rate clocks. These are used when calculating
648 * what clock and divisor to use for the required baud rate. Also
649 * define the maximum baud rate allowed, and the default base baud.
650 */
651static int stl_cd1400clkdivs[] = {
652 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
653};
654
655/*****************************************************************************/
656
657/*
658 * SC26198 UART specific data initization.
659 */
660static uart_t stl_sc26198uart = {
661 stl_sc26198panelinit,
662 stl_sc26198portinit,
663 stl_sc26198setport,
664 stl_sc26198getsignals,
665 stl_sc26198setsignals,
666 stl_sc26198enablerxtx,
667 stl_sc26198startrxtx,
668 stl_sc26198disableintrs,
669 stl_sc26198sendbreak,
670 stl_sc26198flowctrl,
671 stl_sc26198sendflow,
672 stl_sc26198flush,
673 stl_sc26198datastate,
674 stl_sc26198intr
675};
676
677/*
678 * Define the offsets within the register bank of a sc26198 based panel.
679 */
680#define XP_DATA 0
681#define XP_ADDR 1
682#define XP_MODID 2
683#define XP_STATUS 2
684#define XP_IACK 3
685
686#define XP_BANKSIZE 4
687
688/*
689 * Define the sc26198 baud rate table. Offsets within the table
690 * represent the actual baud rate selector of sc26198 registers.
691 */
692static unsigned int sc26198_baudtable[] = {
693 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
694 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
695 230400, 460800, 921600
696};
697
Tobias Klauserfe971072006-01-09 20:54:02 -0800698#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
700/*****************************************************************************/
701
702/*
703 * Define the driver info for a user level control device. Used mainly
704 * to get at port stats - only not using the port device itself.
705 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700706static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 .owner = THIS_MODULE,
708 .ioctl = stl_memioctl,
709};
710
711/*****************************************************************************/
712
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800713static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
715/*
716 * Loadable module initialization stuff.
717 */
718
719static int __init stallion_module_init(void)
720{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 stl_init();
Jesper Juhl014c2542006-01-15 02:37:08 +0100722 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723}
724
725/*****************************************************************************/
726
727static void __exit stallion_module_exit(void)
728{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800729 struct stlbrd *brdp;
730 struct stlpanel *panelp;
731 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 int i, j, k;
733
Jiri Slabya0564e12006-12-08 02:38:37 -0800734 pr_debug("cleanup_module()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
736 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
737 stl_drvversion);
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739/*
740 * Free up all allocated resources used by the ports. This includes
741 * memory and interrupts. As part of this process we will also do
742 * a hangup on every open port - to try to flush out any processes
743 * hanging onto ports.
744 */
745 i = tty_unregister_driver(stl_serial);
746 put_tty_driver(stl_serial);
747 if (i) {
748 printk("STALLION: failed to un-register tty driver, "
749 "errno=%d\n", -i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 return;
751 }
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -0700752 for (i = 0; i < 4; i++)
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800753 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
755 printk("STALLION: failed to un-register serial memory device, "
756 "errno=%d\n", -i);
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800757 class_destroy(stallion_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 for (i = 0; (i < stl_nrbrds); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800760 if ((brdp = stl_brds[i]) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 continue;
762
763 free_irq(brdp->irq, brdp);
764
765 for (j = 0; (j < STL_MAXPANELS); j++) {
766 panelp = brdp->panels[j];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800767 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 continue;
769 for (k = 0; (k < STL_PORTSPERPANEL); k++) {
770 portp = panelp->ports[k];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800771 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 continue;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800773 if (portp->tty != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 stl_hangup(portp->tty);
Jesper Juhl735d5662005-11-07 01:01:29 -0800775 kfree(portp->tx.buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 kfree(portp);
777 }
778 kfree(panelp);
779 }
780
781 release_region(brdp->ioaddr1, brdp->iosize1);
782 if (brdp->iosize2 > 0)
783 release_region(brdp->ioaddr2, brdp->iosize2);
784
785 kfree(brdp);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800786 stl_brds[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788}
789
790module_init(stallion_module_init);
791module_exit(stallion_module_exit);
792
793/*****************************************************************************/
794
795/*
796 * Check for any arguments passed in on the module load command line.
797 */
798
799static void stl_argbrds(void)
800{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800801 struct stlconf conf;
802 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 int i;
804
Jiri Slabya0564e12006-12-08 02:38:37 -0800805 pr_debug("stl_argbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 for (i = stl_nrbrds; (i < stl_nargs); i++) {
808 memset(&conf, 0, sizeof(conf));
809 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
810 continue;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800811 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 continue;
813 stl_nrbrds = i + 1;
814 brdp->brdnr = i;
815 brdp->brdtype = conf.brdtype;
816 brdp->ioaddr1 = conf.ioaddr1;
817 brdp->ioaddr2 = conf.ioaddr2;
818 brdp->irq = conf.irq;
819 brdp->irqtype = conf.irqtype;
820 stl_brdinit(brdp);
821 }
822}
823
824/*****************************************************************************/
825
826/*
827 * Convert an ascii string number into an unsigned long.
828 */
829
830static unsigned long stl_atol(char *str)
831{
832 unsigned long val;
833 int base, c;
834 char *sp;
835
836 val = 0;
837 sp = str;
838 if ((*sp == '0') && (*(sp+1) == 'x')) {
839 base = 16;
840 sp += 2;
841 } else if (*sp == '0') {
842 base = 8;
843 sp++;
844 } else {
845 base = 10;
846 }
847
848 for (; (*sp != 0); sp++) {
849 c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');
850 if ((c < 0) || (c >= base)) {
851 printk("STALLION: invalid argument %s\n", str);
852 val = 0;
853 break;
854 }
855 val = (val * base) + c;
856 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100857 return val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858}
859
860/*****************************************************************************/
861
862/*
863 * Parse the supplied argument string, into the board conf struct.
864 */
865
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800866static int stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
868 char *sp;
Tobias Klauserfe971072006-01-09 20:54:02 -0800869 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Jiri Slabya0564e12006-12-08 02:38:37 -0800871 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Jiri Slaby615e4a72006-12-08 02:38:38 -0800873 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100874 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
876 for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
877 *sp = TOLOWER(*sp);
878
Tobias Klauserfe971072006-01-09 20:54:02 -0800879 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
881 break;
882 }
Tobias Klauserfe971072006-01-09 20:54:02 -0800883 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800885 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 }
887
888 confp->brdtype = stl_brdstr[i].type;
889
890 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800891 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 confp->ioaddr1 = stl_atol(argp[i]);
893 i++;
894 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800895 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 confp->ioaddr2 = stl_atol(argp[i]);
897 i++;
898 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800899 if ((argp[i] != NULL) && (*argp[i] != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 confp->irq = stl_atol(argp[i]);
Jesper Juhl014c2542006-01-15 02:37:08 +0100901 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902}
903
904/*****************************************************************************/
905
906/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 * Allocate a new board structure. Fill out the basic info in it.
908 */
909
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800910static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800912 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800914 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800915 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700916 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800917 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800918 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100922 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923}
924
925/*****************************************************************************/
926
927static int stl_open(struct tty_struct *tty, struct file *filp)
928{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800929 struct stlport *portp;
930 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 unsigned int minordev;
932 int brdnr, panelnr, portnr, rc;
933
Jiri Slabya0564e12006-12-08 02:38:37 -0800934 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
936 minordev = tty->index;
937 brdnr = MINOR2BRD(minordev);
938 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100939 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800941 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100942 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 minordev = MINOR2PORT(minordev);
944 for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800945 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 break;
947 if (minordev < brdp->panels[panelnr]->nrports) {
948 portnr = minordev;
949 break;
950 }
951 minordev -= brdp->panels[panelnr]->nrports;
952 }
953 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100954 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800957 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100958 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960/*
961 * On the first open of the device setup the port hardware, and
962 * initialize the per port data structure.
963 */
964 portp->tty = tty;
965 tty->driver_data = portp;
966 portp->refcount++;
967
968 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800969 if (!portp->tx.buf) {
970 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
971 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100972 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 portp->tx.head = portp->tx.buf;
974 portp->tx.tail = portp->tx.buf;
975 }
976 stl_setport(portp, tty->termios);
977 portp->sigs = stl_getsignals(portp);
978 stl_setsignals(portp, 1, 1);
979 stl_enablerxtx(portp, 1, 1);
980 stl_startrxtx(portp, 1, 0);
981 clear_bit(TTY_IO_ERROR, &tty->flags);
982 portp->flags |= ASYNC_INITIALIZED;
983 }
984
985/*
986 * Check if this port is in the middle of closing. If so then wait
987 * until it is closed then return error status, based on flag settings.
988 * The sleep here does not need interrupt protection since the wakeup
989 * for it is done with the same context.
990 */
991 if (portp->flags & ASYNC_CLOSING) {
992 interruptible_sleep_on(&portp->close_wait);
993 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100994 return -EAGAIN;
995 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 }
997
998/*
999 * Based on type of open being done check if it can overlap with any
1000 * previous opens still in effect. If we are a normal serial device
1001 * then also we might have to wait for carrier.
1002 */
1003 if (!(filp->f_flags & O_NONBLOCK)) {
1004 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +01001005 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007 portp->flags |= ASYNC_NORMAL_ACTIVE;
1008
Jesper Juhl014c2542006-01-15 02:37:08 +01001009 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010}
1011
1012/*****************************************************************************/
1013
1014/*
1015 * Possibly need to wait for carrier (DCD signal) to come high. Say
1016 * maybe because if we are clocal then we don't need to wait...
1017 */
1018
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001019static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
1021 unsigned long flags;
1022 int rc, doclocal;
1023
Jiri Slabya0564e12006-12-08 02:38:37 -08001024 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
1026 rc = 0;
1027 doclocal = 0;
1028
Alan Coxb65b5b52006-06-27 02:54:05 -07001029 spin_lock_irqsave(&stallion_lock, flags);
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 if (portp->tty->termios->c_cflag & CLOCAL)
1032 doclocal++;
1033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 portp->openwaitcnt++;
1035 if (! tty_hung_up_p(filp))
1036 portp->refcount--;
1037
1038 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001039 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 stl_setsignals(portp, 1, 1);
1041 if (tty_hung_up_p(filp) ||
1042 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
1043 if (portp->flags & ASYNC_HUP_NOTIFY)
1044 rc = -EBUSY;
1045 else
1046 rc = -ERESTARTSYS;
1047 break;
1048 }
1049 if (((portp->flags & ASYNC_CLOSING) == 0) &&
1050 (doclocal || (portp->sigs & TIOCM_CD))) {
1051 break;
1052 }
1053 if (signal_pending(current)) {
1054 rc = -ERESTARTSYS;
1055 break;
1056 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001057 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 interruptible_sleep_on(&portp->open_wait);
1059 }
1060
1061 if (! tty_hung_up_p(filp))
1062 portp->refcount++;
1063 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -07001064 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Jesper Juhl014c2542006-01-15 02:37:08 +01001066 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067}
1068
1069/*****************************************************************************/
1070
1071static void stl_close(struct tty_struct *tty, struct file *filp)
1072{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001073 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 unsigned long flags;
1075
Jiri Slabya0564e12006-12-08 02:38:37 -08001076 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
1078 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001079 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 return;
1081
Alan Coxb65b5b52006-06-27 02:54:05 -07001082 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001084 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 return;
1086 }
1087 if ((tty->count == 1) && (portp->refcount != 1))
1088 portp->refcount = 1;
1089 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -07001090 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 return;
1092 }
1093
1094 portp->refcount = 0;
1095 portp->flags |= ASYNC_CLOSING;
1096
1097/*
1098 * May want to wait for any data to drain before closing. The BUSY
1099 * flag keeps track of whether we are still sending or not - it is
1100 * very accurate for the cd1400, not quite so for the sc26198.
1101 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
1102 */
1103 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -07001104
1105 spin_unlock_irqrestore(&stallion_lock, flags);
1106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1108 tty_wait_until_sent(tty, portp->closing_wait);
1109 stl_waituntilsent(tty, (HZ / 2));
1110
Alan Coxb65b5b52006-06-27 02:54:05 -07001111
1112 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -07001114 spin_unlock_irqrestore(&stallion_lock, flags);
1115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 stl_disableintrs(portp);
1117 if (tty->termios->c_cflag & HUPCL)
1118 stl_setsignals(portp, 0, 0);
1119 stl_enablerxtx(portp, 0, 0);
1120 stl_flushbuffer(tty);
1121 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001122 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001124 portp->tx.buf = NULL;
1125 portp->tx.head = NULL;
1126 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 }
1128 set_bit(TTY_IO_ERROR, &tty->flags);
1129 tty_ldisc_flush(tty);
1130
1131 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001132 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 if (portp->openwaitcnt) {
1135 if (portp->close_delay)
1136 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
1137 wake_up_interruptible(&portp->open_wait);
1138 }
1139
1140 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1141 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142}
1143
1144/*****************************************************************************/
1145
1146/*
1147 * Write routine. Take data and stuff it in to the TX ring queue.
1148 * If transmit interrupts are not running then start them.
1149 */
1150
1151static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
1152{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001153 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 unsigned int len, stlen;
1155 unsigned char *chbuf;
1156 char *head, *tail;
1157
Jiri Slabya0564e12006-12-08 02:38:37 -08001158 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001161 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001162 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001163 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001164 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166/*
1167 * If copying direct from user space we must cater for page faults,
1168 * causing us to "sleep" here for a while. To handle this copy in all
1169 * the data we need now, into a local buffer. Then when we got it all
1170 * copy it into the TX buffer.
1171 */
1172 chbuf = (unsigned char *) buf;
1173
1174 head = portp->tx.head;
1175 tail = portp->tx.tail;
1176 if (head >= tail) {
1177 len = STL_TXBUFSIZE - (head - tail) - 1;
1178 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
1179 } else {
1180 len = tail - head - 1;
1181 stlen = len;
1182 }
1183
1184 len = MIN(len, count);
1185 count = 0;
1186 while (len > 0) {
1187 stlen = MIN(len, stlen);
1188 memcpy(head, chbuf, stlen);
1189 len -= stlen;
1190 chbuf += stlen;
1191 count += stlen;
1192 head += stlen;
1193 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1194 head = portp->tx.buf;
1195 stlen = tail - head;
1196 }
1197 }
1198 portp->tx.head = head;
1199
1200 clear_bit(ASYI_TXLOW, &portp->istate);
1201 stl_startrxtx(portp, -1, 1);
1202
Jesper Juhl014c2542006-01-15 02:37:08 +01001203 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204}
1205
1206/*****************************************************************************/
1207
1208static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1209{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001210 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 unsigned int len;
1212 char *head, *tail;
1213
Jiri Slabya0564e12006-12-08 02:38:37 -08001214 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Jiri Slaby615e4a72006-12-08 02:38:38 -08001216 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 return;
1218 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001219 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001221 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 return;
1223
1224 head = portp->tx.head;
1225 tail = portp->tx.tail;
1226
1227 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1228 len--;
1229
1230 if (len > 0) {
1231 *head++ = ch;
1232 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1233 head = portp->tx.buf;
1234 }
1235 portp->tx.head = head;
1236}
1237
1238/*****************************************************************************/
1239
1240/*
1241 * If there are any characters in the buffer then make sure that TX
1242 * interrupts are on and get'em out. Normally used after the putchar
1243 * routine has been called.
1244 */
1245
1246static void stl_flushchars(struct tty_struct *tty)
1247{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001248 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
Jiri Slabya0564e12006-12-08 02:38:37 -08001250 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Jiri Slaby615e4a72006-12-08 02:38:38 -08001252 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 return;
1254 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001255 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001257 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 return;
1259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 stl_startrxtx(portp, -1, 1);
1261}
1262
1263/*****************************************************************************/
1264
1265static int stl_writeroom(struct tty_struct *tty)
1266{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001267 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 char *head, *tail;
1269
Jiri Slabya0564e12006-12-08 02:38:37 -08001270 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
Jiri Slaby615e4a72006-12-08 02:38:38 -08001272 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001273 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001275 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001276 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001277 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001278 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
1280 head = portp->tx.head;
1281 tail = portp->tx.tail;
Jesper Juhl014c2542006-01-15 02:37:08 +01001282 return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283}
1284
1285/*****************************************************************************/
1286
1287/*
1288 * Return number of chars in the TX buffer. Normally we would just
1289 * calculate the number of chars in the buffer and return that, but if
1290 * the buffer is empty and TX interrupts are still on then we return
1291 * that the buffer still has 1 char in it. This way whoever called us
1292 * will not think that ALL chars have drained - since the UART still
1293 * must have some chars in it (we are busy after all).
1294 */
1295
1296static int stl_charsinbuffer(struct tty_struct *tty)
1297{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001298 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 unsigned int size;
1300 char *head, *tail;
1301
Jiri Slabya0564e12006-12-08 02:38:37 -08001302 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Jiri Slaby615e4a72006-12-08 02:38:38 -08001304 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001305 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001307 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001308 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001309 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001310 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
1312 head = portp->tx.head;
1313 tail = portp->tx.tail;
1314 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1315 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1316 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001317 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318}
1319
1320/*****************************************************************************/
1321
1322/*
1323 * Generate the serial struct info.
1324 */
1325
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001326static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327{
1328 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001329 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Jiri Slabya0564e12006-12-08 02:38:37 -08001331 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
1333 memset(&sio, 0, sizeof(struct serial_struct));
1334 sio.line = portp->portnr;
1335 sio.port = portp->ioaddr;
1336 sio.flags = portp->flags;
1337 sio.baud_base = portp->baud_base;
1338 sio.close_delay = portp->close_delay;
1339 sio.closing_wait = portp->closing_wait;
1340 sio.custom_divisor = portp->custom_divisor;
1341 sio.hub6 = 0;
1342 if (portp->uartp == &stl_cd1400uart) {
1343 sio.type = PORT_CIRRUS;
1344 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1345 } else {
1346 sio.type = PORT_UNKNOWN;
1347 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1348 }
1349
1350 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001351 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 sio.irq = brdp->irq;
1353
1354 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1355}
1356
1357/*****************************************************************************/
1358
1359/*
1360 * Set port according to the serial struct info.
1361 * At this point we do not do any auto-configure stuff, so we will
1362 * just quietly ignore any requests to change irq, etc.
1363 */
1364
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001365static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366{
1367 struct serial_struct sio;
1368
Jiri Slabya0564e12006-12-08 02:38:37 -08001369 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
1371 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1372 return -EFAULT;
1373 if (!capable(CAP_SYS_ADMIN)) {
1374 if ((sio.baud_base != portp->baud_base) ||
1375 (sio.close_delay != portp->close_delay) ||
1376 ((sio.flags & ~ASYNC_USR_MASK) !=
1377 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001378 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 }
1380
1381 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1382 (sio.flags & ASYNC_USR_MASK);
1383 portp->baud_base = sio.baud_base;
1384 portp->close_delay = sio.close_delay;
1385 portp->closing_wait = sio.closing_wait;
1386 portp->custom_divisor = sio.custom_divisor;
1387 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001388 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389}
1390
1391/*****************************************************************************/
1392
1393static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1394{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001395 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
Jiri Slaby615e4a72006-12-08 02:38:38 -08001397 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001398 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001400 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001401 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001403 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
1405 return stl_getsignals(portp);
1406}
1407
1408static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1409 unsigned int set, unsigned int clear)
1410{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001411 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 int rts = -1, dtr = -1;
1413
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001415 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001417 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001418 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001420 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
1422 if (set & TIOCM_RTS)
1423 rts = 1;
1424 if (set & TIOCM_DTR)
1425 dtr = 1;
1426 if (clear & TIOCM_RTS)
1427 rts = 0;
1428 if (clear & TIOCM_DTR)
1429 dtr = 0;
1430
1431 stl_setsignals(portp, dtr, rts);
1432 return 0;
1433}
1434
1435static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1436{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001437 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 unsigned int ival;
1439 int rc;
1440 void __user *argp = (void __user *)arg;
1441
Jiri Slabya0564e12006-12-08 02:38:37 -08001442 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1443 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Jiri Slaby615e4a72006-12-08 02:38:38 -08001445 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001446 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001448 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001449 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1452 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
1453 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001454 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 }
1456
1457 rc = 0;
1458
1459 switch (cmd) {
1460 case TIOCGSOFTCAR:
1461 rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
1462 (unsigned __user *) argp);
1463 break;
1464 case TIOCSSOFTCAR:
1465 if (get_user(ival, (unsigned int __user *) arg))
1466 return -EFAULT;
1467 tty->termios->c_cflag =
1468 (tty->termios->c_cflag & ~CLOCAL) |
1469 (ival ? CLOCAL : 0);
1470 break;
1471 case TIOCGSERIAL:
1472 rc = stl_getserial(portp, argp);
1473 break;
1474 case TIOCSSERIAL:
1475 rc = stl_setserial(portp, argp);
1476 break;
1477 case COM_GETPORTSTATS:
1478 rc = stl_getportstats(portp, argp);
1479 break;
1480 case COM_CLRPORTSTATS:
1481 rc = stl_clrportstats(portp, argp);
1482 break;
1483 case TIOCSERCONFIG:
1484 case TIOCSERGWILD:
1485 case TIOCSERSWILD:
1486 case TIOCSERGETLSR:
1487 case TIOCSERGSTRUCT:
1488 case TIOCSERGETMULTI:
1489 case TIOCSERSETMULTI:
1490 default:
1491 rc = -ENOIOCTLCMD;
1492 break;
1493 }
1494
Jesper Juhl014c2542006-01-15 02:37:08 +01001495 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496}
1497
1498/*****************************************************************************/
1499
1500static void stl_settermios(struct tty_struct *tty, struct termios *old)
1501{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001502 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 struct termios *tiosp;
1504
Jiri Slabya0564e12006-12-08 02:38:37 -08001505 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Jiri Slaby615e4a72006-12-08 02:38:38 -08001507 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 return;
1509 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001510 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 return;
1512
1513 tiosp = tty->termios;
1514 if ((tiosp->c_cflag == old->c_cflag) &&
1515 (tiosp->c_iflag == old->c_iflag))
1516 return;
1517
1518 stl_setport(portp, tiosp);
1519 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1520 -1);
1521 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1522 tty->hw_stopped = 0;
1523 stl_start(tty);
1524 }
1525 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1526 wake_up_interruptible(&portp->open_wait);
1527}
1528
1529/*****************************************************************************/
1530
1531/*
1532 * Attempt to flow control who ever is sending us data. Based on termios
1533 * settings use software or/and hardware flow control.
1534 */
1535
1536static void stl_throttle(struct tty_struct *tty)
1537{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001538 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
Jiri Slabya0564e12006-12-08 02:38:37 -08001540 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Jiri Slaby615e4a72006-12-08 02:38:38 -08001542 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 return;
1544 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001545 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 return;
1547 stl_flowctrl(portp, 0);
1548}
1549
1550/*****************************************************************************/
1551
1552/*
1553 * Unflow control the device sending us data...
1554 */
1555
1556static void stl_unthrottle(struct tty_struct *tty)
1557{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001558 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
Jiri Slabya0564e12006-12-08 02:38:37 -08001560 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Jiri Slaby615e4a72006-12-08 02:38:38 -08001562 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 return;
1564 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001565 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 return;
1567 stl_flowctrl(portp, 1);
1568}
1569
1570/*****************************************************************************/
1571
1572/*
1573 * Stop the transmitter. Basically to do this we will just turn TX
1574 * interrupts off.
1575 */
1576
1577static void stl_stop(struct tty_struct *tty)
1578{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001579 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Jiri Slabya0564e12006-12-08 02:38:37 -08001581 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Jiri Slaby615e4a72006-12-08 02:38:38 -08001583 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 return;
1585 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001586 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 return;
1588 stl_startrxtx(portp, -1, 0);
1589}
1590
1591/*****************************************************************************/
1592
1593/*
1594 * Start the transmitter again. Just turn TX interrupts back on.
1595 */
1596
1597static void stl_start(struct tty_struct *tty)
1598{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001599 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Jiri Slabya0564e12006-12-08 02:38:37 -08001601 pr_debug("stl_start(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Jiri Slaby615e4a72006-12-08 02:38:38 -08001603 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 return;
1605 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001606 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 return;
1608 stl_startrxtx(portp, -1, 1);
1609}
1610
1611/*****************************************************************************/
1612
1613/*
1614 * Hangup this port. This is pretty much like closing the port, only
1615 * a little more brutal. No waiting for data to drain. Shutdown the
1616 * port and maybe drop signals.
1617 */
1618
1619static void stl_hangup(struct tty_struct *tty)
1620{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001621 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Jiri Slabya0564e12006-12-08 02:38:37 -08001623 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Jiri Slaby615e4a72006-12-08 02:38:38 -08001625 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 return;
1627 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001628 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 return;
1630
1631 portp->flags &= ~ASYNC_INITIALIZED;
1632 stl_disableintrs(portp);
1633 if (tty->termios->c_cflag & HUPCL)
1634 stl_setsignals(portp, 0, 0);
1635 stl_enablerxtx(portp, 0, 0);
1636 stl_flushbuffer(tty);
1637 portp->istate = 0;
1638 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001639 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001641 portp->tx.buf = NULL;
1642 portp->tx.head = NULL;
1643 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001645 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1647 portp->refcount = 0;
1648 wake_up_interruptible(&portp->open_wait);
1649}
1650
1651/*****************************************************************************/
1652
1653static void stl_flushbuffer(struct tty_struct *tty)
1654{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001655 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
Jiri Slabya0564e12006-12-08 02:38:37 -08001657 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
Jiri Slaby615e4a72006-12-08 02:38:38 -08001659 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 return;
1661 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001662 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 return;
1664
1665 stl_flush(portp);
1666 tty_wakeup(tty);
1667}
1668
1669/*****************************************************************************/
1670
1671static void stl_breakctl(struct tty_struct *tty, int state)
1672{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001673 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674
Jiri Slabya0564e12006-12-08 02:38:37 -08001675 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
Jiri Slaby615e4a72006-12-08 02:38:38 -08001677 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 return;
1679 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001680 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 return;
1682
1683 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1684}
1685
1686/*****************************************************************************/
1687
1688static void stl_waituntilsent(struct tty_struct *tty, int timeout)
1689{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001690 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 unsigned long tend;
1692
Jiri Slabya0564e12006-12-08 02:38:37 -08001693 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
Jiri Slaby615e4a72006-12-08 02:38:38 -08001695 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 return;
1697 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001698 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 return;
1700
1701 if (timeout == 0)
1702 timeout = HZ;
1703 tend = jiffies + timeout;
1704
1705 while (stl_datastate(portp)) {
1706 if (signal_pending(current))
1707 break;
1708 msleep_interruptible(20);
1709 if (time_after_eq(jiffies, tend))
1710 break;
1711 }
1712}
1713
1714/*****************************************************************************/
1715
1716static void stl_sendxchar(struct tty_struct *tty, char ch)
1717{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001718 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719
Jiri Slabya0564e12006-12-08 02:38:37 -08001720 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Jiri Slaby615e4a72006-12-08 02:38:38 -08001722 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 return;
1724 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001725 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 return;
1727
1728 if (ch == STOP_CHAR(tty))
1729 stl_sendflow(portp, 0);
1730 else if (ch == START_CHAR(tty))
1731 stl_sendflow(portp, 1);
1732 else
1733 stl_putchar(tty, ch);
1734}
1735
1736/*****************************************************************************/
1737
1738#define MAXLINE 80
1739
1740/*
1741 * Format info for a specified port. The line is deliberately limited
1742 * to 80 characters. (If it is too long it will be truncated, if too
1743 * short then padded with spaces).
1744 */
1745
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001746static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747{
1748 char *sp;
1749 int sigs, cnt;
1750
1751 sp = pos;
1752 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1753 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1754 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1755
1756 if (portp->stats.rxframing)
1757 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1758 if (portp->stats.rxparity)
1759 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1760 if (portp->stats.rxbreaks)
1761 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1762 if (portp->stats.rxoverrun)
1763 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1764
1765 sigs = stl_getsignals(portp);
1766 cnt = sprintf(sp, "%s%s%s%s%s ",
1767 (sigs & TIOCM_RTS) ? "|RTS" : "",
1768 (sigs & TIOCM_CTS) ? "|CTS" : "",
1769 (sigs & TIOCM_DTR) ? "|DTR" : "",
1770 (sigs & TIOCM_CD) ? "|DCD" : "",
1771 (sigs & TIOCM_DSR) ? "|DSR" : "");
1772 *sp = ' ';
1773 sp += cnt;
1774
1775 for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)
1776 *sp++ = ' ';
1777 if (cnt >= MAXLINE)
1778 pos[(MAXLINE - 2)] = '+';
1779 pos[(MAXLINE - 1)] = '\n';
1780
Jesper Juhl014c2542006-01-15 02:37:08 +01001781 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782}
1783
1784/*****************************************************************************/
1785
1786/*
1787 * Port info, read from the /proc file system.
1788 */
1789
1790static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1791{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001792 struct stlbrd *brdp;
1793 struct stlpanel *panelp;
1794 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 int brdnr, panelnr, portnr, totalport;
1796 int curoff, maxoff;
1797 char *pos;
1798
Jiri Slabya0564e12006-12-08 02:38:37 -08001799 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1800 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
1802 pos = page;
1803 totalport = 0;
1804 curoff = 0;
1805
1806 if (off == 0) {
1807 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1808 stl_drvversion);
1809 while (pos < (page + MAXLINE - 1))
1810 *pos++ = ' ';
1811 *pos++ = '\n';
1812 }
1813 curoff = MAXLINE;
1814
1815/*
1816 * We scan through for each board, panel and port. The offset is
1817 * calculated on the fly, and irrelevant ports are skipped.
1818 */
1819 for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
1820 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001821 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 continue;
1823 if (brdp->state == 0)
1824 continue;
1825
1826 maxoff = curoff + (brdp->nrports * MAXLINE);
1827 if (off >= maxoff) {
1828 curoff = maxoff;
1829 continue;
1830 }
1831
1832 totalport = brdnr * STL_MAXPORTS;
1833 for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
1834 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001835 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 continue;
1837
1838 maxoff = curoff + (panelp->nrports * MAXLINE);
1839 if (off >= maxoff) {
1840 curoff = maxoff;
1841 totalport += panelp->nrports;
1842 continue;
1843 }
1844
1845 for (portnr = 0; (portnr < panelp->nrports); portnr++,
1846 totalport++) {
1847 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001848 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 continue;
1850 if (off >= (curoff += MAXLINE))
1851 continue;
1852 if ((pos - page + MAXLINE) > count)
1853 goto stl_readdone;
1854 pos += stl_portinfo(portp, totalport, pos);
1855 }
1856 }
1857 }
1858
1859 *eof = 1;
1860
1861stl_readdone:
1862 *start = page;
Jesper Juhl014c2542006-01-15 02:37:08 +01001863 return (pos - page);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864}
1865
1866/*****************************************************************************/
1867
1868/*
1869 * All board interrupts are vectored through here first. This code then
1870 * calls off to the approrpriate board interrupt handlers.
1871 */
1872
David Howells7d12e782006-10-05 14:55:46 +01001873static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001875 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Jiri Slabya0564e12006-12-08 02:38:37 -08001877 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878
1879 return IRQ_RETVAL((* brdp->isr)(brdp));
1880}
1881
1882/*****************************************************************************/
1883
1884/*
1885 * Interrupt service routine for EasyIO board types.
1886 */
1887
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001888static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001890 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 unsigned int iobase;
1892 int handled = 0;
1893
Alan Coxb65b5b52006-06-27 02:54:05 -07001894 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 panelp = brdp->panels[0];
1896 iobase = panelp->iobase;
1897 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1898 handled = 1;
1899 (* panelp->isr)(panelp, iobase);
1900 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001901 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 return handled;
1903}
1904
1905/*****************************************************************************/
1906
1907/*
1908 * Interrupt service routine for ECH-AT board types.
1909 */
1910
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001911static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001913 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 unsigned int ioaddr;
1915 int bnknr;
1916 int handled = 0;
1917
1918 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1919
1920 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1921 handled = 1;
1922 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1923 ioaddr = brdp->bnkstataddr[bnknr];
1924 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1925 panelp = brdp->bnk2panel[bnknr];
1926 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1927 }
1928 }
1929 }
1930
1931 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1932
1933 return handled;
1934}
1935
1936/*****************************************************************************/
1937
1938/*
1939 * Interrupt service routine for ECH-MCA board types.
1940 */
1941
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001942static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001944 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 unsigned int ioaddr;
1946 int bnknr;
1947 int handled = 0;
1948
1949 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1950 handled = 1;
1951 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1952 ioaddr = brdp->bnkstataddr[bnknr];
1953 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1954 panelp = brdp->bnk2panel[bnknr];
1955 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1956 }
1957 }
1958 }
1959 return handled;
1960}
1961
1962/*****************************************************************************/
1963
1964/*
1965 * Interrupt service routine for ECH-PCI board types.
1966 */
1967
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001968static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001970 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 unsigned int ioaddr;
1972 int bnknr, recheck;
1973 int handled = 0;
1974
1975 while (1) {
1976 recheck = 0;
1977 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
1978 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1979 ioaddr = brdp->bnkstataddr[bnknr];
1980 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1981 panelp = brdp->bnk2panel[bnknr];
1982 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1983 recheck++;
1984 handled = 1;
1985 }
1986 }
1987 if (! recheck)
1988 break;
1989 }
1990 return handled;
1991}
1992
1993/*****************************************************************************/
1994
1995/*
1996 * Interrupt service routine for ECH-8/64-PCI board types.
1997 */
1998
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001999static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002001 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 unsigned int ioaddr;
2003 int bnknr;
2004 int handled = 0;
2005
2006 while (inb(brdp->ioctrl) & 0x1) {
2007 handled = 1;
2008 for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
2009 ioaddr = brdp->bnkstataddr[bnknr];
2010 if (inb(ioaddr) & ECH_PNLINTRPEND) {
2011 panelp = brdp->bnk2panel[bnknr];
2012 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
2013 }
2014 }
2015 }
2016
2017 return handled;
2018}
2019
2020/*****************************************************************************/
2021
2022/*
2023 * Service an off-level request for some channel.
2024 */
Al Viro3e577a82006-12-06 18:41:45 +00002025static void stl_offintr(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002027 struct stlport *portp = container_of(work, struct stlport, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 struct tty_struct *tty;
2029 unsigned int oldsigs;
2030
Jiri Slabya0564e12006-12-08 02:38:37 -08002031 pr_debug("stl_offintr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
Jiri Slaby615e4a72006-12-08 02:38:38 -08002033 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 return;
2035
2036 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08002037 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 return;
2039
2040 lock_kernel();
2041 if (test_bit(ASYI_TXLOW, &portp->istate)) {
2042 tty_wakeup(tty);
2043 }
2044 if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
2045 clear_bit(ASYI_DCDCHANGE, &portp->istate);
2046 oldsigs = portp->sigs;
2047 portp->sigs = stl_getsignals(portp);
2048 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
2049 wake_up_interruptible(&portp->open_wait);
2050 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
2051 if (portp->flags & ASYNC_CHECK_CD)
2052 tty_hangup(tty); /* FIXME: module removal race here - AKPM */
2053 }
2054 }
2055 unlock_kernel();
2056}
2057
2058/*****************************************************************************/
2059
2060/*
2061 * Initialize all the ports on a panel.
2062 */
2063
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002064static int __init stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002066 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 int chipmask, i;
2068
Jiri Slabya0564e12006-12-08 02:38:37 -08002069 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
2071 chipmask = stl_panelinit(brdp, panelp);
2072
2073/*
2074 * All UART's are initialized (if found!). Now go through and setup
2075 * each ports data structures.
2076 */
2077 for (i = 0; (i < panelp->nrports); i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002078 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002079 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002081 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 break;
2083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
2085 portp->magic = STL_PORTMAGIC;
2086 portp->portnr = i;
2087 portp->brdnr = panelp->brdnr;
2088 portp->panelnr = panelp->panelnr;
2089 portp->uartp = panelp->uartp;
2090 portp->clk = brdp->clk;
2091 portp->baud_base = STL_BAUDBASE;
2092 portp->close_delay = STL_CLOSEDELAY;
2093 portp->closing_wait = 30 * HZ;
Al Viro3e577a82006-12-06 18:41:45 +00002094 INIT_WORK(&portp->tqueue, stl_offintr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 init_waitqueue_head(&portp->open_wait);
2096 init_waitqueue_head(&portp->close_wait);
2097 portp->stats.brd = portp->brdnr;
2098 portp->stats.panel = portp->panelnr;
2099 portp->stats.port = portp->portnr;
2100 panelp->ports[i] = portp;
2101 stl_portinit(brdp, panelp, portp);
2102 }
2103
2104 return(0);
2105}
2106
2107/*****************************************************************************/
2108
2109/*
2110 * Try to find and initialize an EasyIO board.
2111 */
2112
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002113static inline int stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002115 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 unsigned int status;
2117 char *name;
2118 int rc;
2119
Jiri Slabya0564e12006-12-08 02:38:37 -08002120 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
2122 brdp->ioctrl = brdp->ioaddr1 + 1;
2123 brdp->iostatus = brdp->ioaddr1 + 2;
2124
2125 status = inb(brdp->iostatus);
2126 if ((status & EIO_IDBITMASK) == EIO_MK3)
2127 brdp->ioctrl++;
2128
2129/*
2130 * Handle board specific stuff now. The real difference is PCI
2131 * or not PCI.
2132 */
2133 if (brdp->brdtype == BRD_EASYIOPCI) {
2134 brdp->iosize1 = 0x80;
2135 brdp->iosize2 = 0x80;
2136 name = "serial(EIO-PCI)";
2137 outb(0x41, (brdp->ioaddr2 + 0x4c));
2138 } else {
2139 brdp->iosize1 = 8;
2140 name = "serial(EIO)";
2141 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2142 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2143 printk("STALLION: invalid irq=%d for brd=%d\n",
2144 brdp->irq, brdp->brdnr);
2145 return(-EINVAL);
2146 }
2147 outb((stl_vecmap[brdp->irq] | EIO_0WS |
2148 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
2149 brdp->ioctrl);
2150 }
2151
2152 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2153 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2154 "%x conflicts with another device\n", brdp->brdnr,
2155 brdp->ioaddr1);
2156 return(-EBUSY);
2157 }
2158
2159 if (brdp->iosize2 > 0)
2160 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2161 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2162 "address %x conflicts with another device\n",
2163 brdp->brdnr, brdp->ioaddr2);
2164 printk(KERN_WARNING "STALLION: Warning, also "
2165 "releasing board %d I/O address %x \n",
2166 brdp->brdnr, brdp->ioaddr1);
2167 release_region(brdp->ioaddr1, brdp->iosize1);
2168 return(-EBUSY);
2169 }
2170
2171/*
2172 * Everything looks OK, so let's go ahead and probe for the hardware.
2173 */
2174 brdp->clk = CD1400_CLK;
2175 brdp->isr = stl_eiointr;
2176
2177 switch (status & EIO_IDBITMASK) {
2178 case EIO_8PORTM:
2179 brdp->clk = CD1400_CLK8M;
2180 /* fall thru */
2181 case EIO_8PORTRS:
2182 case EIO_8PORTDI:
2183 brdp->nrports = 8;
2184 break;
2185 case EIO_4PORTRS:
2186 brdp->nrports = 4;
2187 break;
2188 case EIO_MK3:
2189 switch (status & EIO_BRDMASK) {
2190 case ID_BRD4:
2191 brdp->nrports = 4;
2192 break;
2193 case ID_BRD8:
2194 brdp->nrports = 8;
2195 break;
2196 case ID_BRD16:
2197 brdp->nrports = 16;
2198 break;
2199 default:
2200 return(-ENODEV);
2201 }
2202 break;
2203 default:
2204 return(-ENODEV);
2205 }
2206
2207/*
2208 * We have verified that the board is actually present, so now we
2209 * can complete the setup.
2210 */
2211
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002212 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002213 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002215 "(size=%Zd)\n", sizeof(struct stlpanel));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002216 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
2219 panelp->magic = STL_PANELMAGIC;
2220 panelp->brdnr = brdp->brdnr;
2221 panelp->panelnr = 0;
2222 panelp->nrports = brdp->nrports;
2223 panelp->iobase = brdp->ioaddr1;
2224 panelp->hwid = status;
2225 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002226 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 panelp->isr = stl_sc26198intr;
2228 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002229 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 panelp->isr = stl_cd1400eiointr;
2231 }
2232
2233 brdp->panels[0] = panelp;
2234 brdp->nrpanels = 1;
2235 brdp->state |= BRD_FOUND;
2236 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002237 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 printk("STALLION: failed to register interrupt "
2239 "routine for %s irq=%d\n", name, brdp->irq);
2240 rc = -ENODEV;
2241 } else {
2242 rc = 0;
2243 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002244 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245}
2246
2247/*****************************************************************************/
2248
2249/*
2250 * Try to find an ECH board and initialize it. This code is capable of
2251 * dealing with all types of ECH board.
2252 */
2253
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002254static inline int stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002256 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 unsigned int status, nxtid, ioaddr, conflict;
2258 int panelnr, banknr, i;
2259 char *name;
2260
Jiri Slabya0564e12006-12-08 02:38:37 -08002261 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 status = 0;
2264 conflict = 0;
2265
2266/*
2267 * Set up the initial board register contents for boards. This varies a
2268 * bit between the different board types. So we need to handle each
2269 * separately. Also do a check that the supplied IRQ is good.
2270 */
2271 switch (brdp->brdtype) {
2272
2273 case BRD_ECH:
2274 brdp->isr = stl_echatintr;
2275 brdp->ioctrl = brdp->ioaddr1 + 1;
2276 brdp->iostatus = brdp->ioaddr1 + 1;
2277 status = inb(brdp->iostatus);
2278 if ((status & ECH_IDBITMASK) != ECH_ID)
2279 return(-ENODEV);
2280 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2281 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2282 printk("STALLION: invalid irq=%d for brd=%d\n",
2283 brdp->irq, brdp->brdnr);
2284 return(-EINVAL);
2285 }
2286 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2287 status |= (stl_vecmap[brdp->irq] << 1);
2288 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2289 brdp->ioctrlval = ECH_INTENABLE |
2290 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
2291 for (i = 0; (i < 10); i++)
2292 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2293 brdp->iosize1 = 2;
2294 brdp->iosize2 = 32;
2295 name = "serial(EC8/32)";
2296 outb(status, brdp->ioaddr1);
2297 break;
2298
2299 case BRD_ECHMC:
2300 brdp->isr = stl_echmcaintr;
2301 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2302 brdp->iostatus = brdp->ioctrl;
2303 status = inb(brdp->iostatus);
2304 if ((status & ECH_IDBITMASK) != ECH_ID)
2305 return(-ENODEV);
2306 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2307 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2308 printk("STALLION: invalid irq=%d for brd=%d\n",
2309 brdp->irq, brdp->brdnr);
2310 return(-EINVAL);
2311 }
2312 outb(ECHMC_BRDRESET, brdp->ioctrl);
2313 outb(ECHMC_INTENABLE, brdp->ioctrl);
2314 brdp->iosize1 = 64;
2315 name = "serial(EC8/32-MC)";
2316 break;
2317
2318 case BRD_ECHPCI:
2319 brdp->isr = stl_echpciintr;
2320 brdp->ioctrl = brdp->ioaddr1 + 2;
2321 brdp->iosize1 = 4;
2322 brdp->iosize2 = 8;
2323 name = "serial(EC8/32-PCI)";
2324 break;
2325
2326 case BRD_ECH64PCI:
2327 brdp->isr = stl_echpci64intr;
2328 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2329 outb(0x43, (brdp->ioaddr1 + 0x4c));
2330 brdp->iosize1 = 0x80;
2331 brdp->iosize2 = 0x80;
2332 name = "serial(EC8/64-PCI)";
2333 break;
2334
2335 default:
2336 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
2337 return(-EINVAL);
2338 break;
2339 }
2340
2341/*
2342 * Check boards for possible IO address conflicts and return fail status
2343 * if an IO conflict found.
2344 */
2345 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2346 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2347 "%x conflicts with another device\n", brdp->brdnr,
2348 brdp->ioaddr1);
2349 return(-EBUSY);
2350 }
2351
2352 if (brdp->iosize2 > 0)
2353 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2354 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2355 "address %x conflicts with another device\n",
2356 brdp->brdnr, brdp->ioaddr2);
2357 printk(KERN_WARNING "STALLION: Warning, also "
2358 "releasing board %d I/O address %x \n",
2359 brdp->brdnr, brdp->ioaddr1);
2360 release_region(brdp->ioaddr1, brdp->iosize1);
2361 return(-EBUSY);
2362 }
2363
2364/*
2365 * Scan through the secondary io address space looking for panels.
2366 * As we find'em allocate and initialize panel structures for each.
2367 */
2368 brdp->clk = CD1400_CLK;
2369 brdp->hwid = status;
2370
2371 ioaddr = brdp->ioaddr2;
2372 banknr = 0;
2373 panelnr = 0;
2374 nxtid = 0;
2375
2376 for (i = 0; (i < STL_MAXPANELS); i++) {
2377 if (brdp->brdtype == BRD_ECHPCI) {
2378 outb(nxtid, brdp->ioctrl);
2379 ioaddr = brdp->ioaddr2;
2380 }
2381 status = inb(ioaddr + ECH_PNLSTATUS);
2382 if ((status & ECH_PNLIDMASK) != nxtid)
2383 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002384 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002385 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002387 "(size=%Zd)\n", sizeof(struct stlpanel));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 break;
2389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390 panelp->magic = STL_PANELMAGIC;
2391 panelp->brdnr = brdp->brdnr;
2392 panelp->panelnr = panelnr;
2393 panelp->iobase = ioaddr;
2394 panelp->pagenr = nxtid;
2395 panelp->hwid = status;
2396 brdp->bnk2panel[banknr] = panelp;
2397 brdp->bnkpageaddr[banknr] = nxtid;
2398 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2399
2400 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002401 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 panelp->isr = stl_sc26198intr;
2403 if (status & ECH_PNL16PORT) {
2404 panelp->nrports = 16;
2405 brdp->bnk2panel[banknr] = panelp;
2406 brdp->bnkpageaddr[banknr] = nxtid;
2407 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2408 ECH_PNLSTATUS;
2409 } else {
2410 panelp->nrports = 8;
2411 }
2412 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002413 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 panelp->isr = stl_cd1400echintr;
2415 if (status & ECH_PNL16PORT) {
2416 panelp->nrports = 16;
2417 panelp->ackmask = 0x80;
2418 if (brdp->brdtype != BRD_ECHPCI)
2419 ioaddr += EREG_BANKSIZE;
2420 brdp->bnk2panel[banknr] = panelp;
2421 brdp->bnkpageaddr[banknr] = ++nxtid;
2422 brdp->bnkstataddr[banknr++] = ioaddr +
2423 ECH_PNLSTATUS;
2424 } else {
2425 panelp->nrports = 8;
2426 panelp->ackmask = 0xc0;
2427 }
2428 }
2429
2430 nxtid++;
2431 ioaddr += EREG_BANKSIZE;
2432 brdp->nrports += panelp->nrports;
2433 brdp->panels[panelnr++] = panelp;
2434 if ((brdp->brdtype != BRD_ECHPCI) &&
2435 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
2436 break;
2437 }
2438
2439 brdp->nrpanels = panelnr;
2440 brdp->nrbnks = banknr;
2441 if (brdp->brdtype == BRD_ECH)
2442 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2443
2444 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002445 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 printk("STALLION: failed to register interrupt "
2447 "routine for %s irq=%d\n", name, brdp->irq);
2448 i = -ENODEV;
2449 } else {
2450 i = 0;
2451 }
2452
2453 return(i);
2454}
2455
2456/*****************************************************************************/
2457
2458/*
2459 * Initialize and configure the specified board.
2460 * Scan through all the boards in the configuration and see what we
2461 * can find. Handle EIO and the ECH boards a little differently here
2462 * since the initial search and setup is very different.
2463 */
2464
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002465static int __init stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466{
2467 int i;
2468
Jiri Slabya0564e12006-12-08 02:38:37 -08002469 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
2471 switch (brdp->brdtype) {
2472 case BRD_EASYIO:
2473 case BRD_EASYIOPCI:
2474 stl_initeio(brdp);
2475 break;
2476 case BRD_ECH:
2477 case BRD_ECHMC:
2478 case BRD_ECHPCI:
2479 case BRD_ECH64PCI:
2480 stl_initech(brdp);
2481 break;
2482 default:
2483 printk("STALLION: board=%d is unknown board type=%d\n",
2484 brdp->brdnr, brdp->brdtype);
2485 return(ENODEV);
2486 }
2487
2488 stl_brds[brdp->brdnr] = brdp;
2489 if ((brdp->state & BRD_FOUND) == 0) {
2490 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2491 stl_brdnames[brdp->brdtype], brdp->brdnr,
2492 brdp->ioaddr1, brdp->irq);
2493 return(ENODEV);
2494 }
2495
2496 for (i = 0; (i < STL_MAXPANELS); i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002497 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 stl_initports(brdp, brdp->panels[i]);
2499
2500 printk("STALLION: %s found, board=%d io=%x irq=%d "
2501 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2502 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2503 brdp->nrports);
2504 return(0);
2505}
2506
2507/*****************************************************************************/
2508
2509/*
2510 * Find the next available board number that is free.
2511 */
2512
2513static inline int stl_getbrdnr(void)
2514{
2515 int i;
2516
2517 for (i = 0; (i < STL_MAXBRDS); i++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002518 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 if (i >= stl_nrbrds)
2520 stl_nrbrds = i + 1;
2521 return(i);
2522 }
2523 }
2524 return(-1);
2525}
2526
2527/*****************************************************************************/
2528
2529#ifdef CONFIG_PCI
2530
2531/*
2532 * We have a Stallion board. Allocate a board structure and
2533 * initialize it. Read its IO and IRQ resources from PCI
2534 * configuration space.
2535 */
2536
2537static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp)
2538{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002539 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
Jiri Slabya0564e12006-12-08 02:38:37 -08002541 pr_debug("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 devp->bus->number, devp->devfn);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
2544 if (pci_enable_device(devp))
2545 return(-EIO);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002546 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 return(-ENOMEM);
2548 if ((brdp->brdnr = stl_getbrdnr()) < 0) {
2549 printk("STALLION: too many boards found, "
2550 "maximum supported %d\n", STL_MAXBRDS);
2551 return(0);
2552 }
2553 brdp->brdtype = brdtype;
2554
2555/*
2556 * Different Stallion boards use the BAR registers in different ways,
2557 * so set up io addresses based on board type.
2558 */
Jiri Slabya0564e12006-12-08 02:38:37 -08002559 pr_debug("%s(%d): BAR[]=%Lx,%Lx,%Lx,%Lx IRQ=%x\n", __FILE__, __LINE__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 pci_resource_start(devp, 0), pci_resource_start(devp, 1),
2561 pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
2563/*
2564 * We have all resources from the board, so let's setup the actual
2565 * board structure now.
2566 */
2567 switch (brdtype) {
2568 case BRD_ECHPCI:
2569 brdp->ioaddr2 = pci_resource_start(devp, 0);
2570 brdp->ioaddr1 = pci_resource_start(devp, 1);
2571 break;
2572 case BRD_ECH64PCI:
2573 brdp->ioaddr2 = pci_resource_start(devp, 2);
2574 brdp->ioaddr1 = pci_resource_start(devp, 1);
2575 break;
2576 case BRD_EASYIOPCI:
2577 brdp->ioaddr1 = pci_resource_start(devp, 2);
2578 brdp->ioaddr2 = pci_resource_start(devp, 1);
2579 break;
2580 default:
2581 printk("STALLION: unknown PCI board type=%d\n", brdtype);
2582 break;
2583 }
2584
2585 brdp->irq = devp->irq;
2586 stl_brdinit(brdp);
2587
2588 return(0);
2589}
2590
2591/*****************************************************************************/
2592
2593/*
2594 * Find all Stallion PCI boards that might be installed. Initialize each
2595 * one as it is found.
2596 */
2597
2598
2599static inline int stl_findpcibrds(void)
2600{
2601 struct pci_dev *dev = NULL;
2602 int i, rc;
2603
Jiri Slabya0564e12006-12-08 02:38:37 -08002604 pr_debug("stl_findpcibrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
2606 for (i = 0; (i < stl_nrpcibrds); i++)
2607 while ((dev = pci_find_device(stl_pcibrds[i].vendid,
2608 stl_pcibrds[i].devid, dev))) {
2609
2610/*
2611 * Found a device on the PCI bus that has our vendor and
2612 * device ID. Need to check now that it is really us.
2613 */
2614 if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)
2615 continue;
2616
2617 rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev);
2618 if (rc)
2619 return(rc);
2620 }
2621
2622 return(0);
2623}
2624
2625#endif
2626
2627/*****************************************************************************/
2628
2629/*
2630 * Scan through all the boards in the configuration and see what we
2631 * can find. Handle EIO and the ECH boards a little differently here
2632 * since the initial search and setup is too different.
2633 */
2634
2635static inline int stl_initbrds(void)
2636{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002637 struct stlbrd *brdp;
2638 struct stlconf *confp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 int i;
2640
Jiri Slabya0564e12006-12-08 02:38:37 -08002641 pr_debug("stl_initbrds()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642
2643 if (stl_nrbrds > STL_MAXBRDS) {
2644 printk("STALLION: too many boards in configuration table, "
2645 "truncating to %d\n", STL_MAXBRDS);
2646 stl_nrbrds = STL_MAXBRDS;
2647 }
2648
2649/*
2650 * Firstly scan the list of static boards configured. Allocate
2651 * resources and initialize the boards as found.
2652 */
2653 for (i = 0; (i < stl_nrbrds); i++) {
2654 confp = &stl_brdconf[i];
2655 stl_parsebrd(confp, stl_brdsp[i]);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002656 if ((brdp = stl_allocbrd()) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 return(-ENOMEM);
2658 brdp->brdnr = i;
2659 brdp->brdtype = confp->brdtype;
2660 brdp->ioaddr1 = confp->ioaddr1;
2661 brdp->ioaddr2 = confp->ioaddr2;
2662 brdp->irq = confp->irq;
2663 brdp->irqtype = confp->irqtype;
2664 stl_brdinit(brdp);
2665 }
2666
2667/*
2668 * Find any dynamically supported boards. That is via module load
2669 * line options or auto-detected on the PCI bus.
2670 */
2671 stl_argbrds();
2672#ifdef CONFIG_PCI
2673 stl_findpcibrds();
2674#endif
2675
2676 return(0);
2677}
2678
2679/*****************************************************************************/
2680
2681/*
2682 * Return the board stats structure to user app.
2683 */
2684
2685static int stl_getbrdstats(combrd_t __user *bp)
2686{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002687 struct stlbrd *brdp;
2688 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 int i;
2690
2691 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2692 return -EFAULT;
2693 if (stl_brdstats.brd >= STL_MAXBRDS)
2694 return(-ENODEV);
2695 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002696 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 return(-ENODEV);
2698
2699 memset(&stl_brdstats, 0, sizeof(combrd_t));
2700 stl_brdstats.brd = brdp->brdnr;
2701 stl_brdstats.type = brdp->brdtype;
2702 stl_brdstats.hwid = brdp->hwid;
2703 stl_brdstats.state = brdp->state;
2704 stl_brdstats.ioaddr = brdp->ioaddr1;
2705 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2706 stl_brdstats.irq = brdp->irq;
2707 stl_brdstats.nrpanels = brdp->nrpanels;
2708 stl_brdstats.nrports = brdp->nrports;
2709 for (i = 0; (i < brdp->nrpanels); i++) {
2710 panelp = brdp->panels[i];
2711 stl_brdstats.panels[i].panel = i;
2712 stl_brdstats.panels[i].hwid = panelp->hwid;
2713 stl_brdstats.panels[i].nrports = panelp->nrports;
2714 }
2715
2716 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2717}
2718
2719/*****************************************************************************/
2720
2721/*
2722 * Resolve the referenced port number into a port struct pointer.
2723 */
2724
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002725static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002727 struct stlbrd *brdp;
2728 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729
2730 if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002731 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002733 if (brdp == NULL)
2734 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002736 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002738 if (panelp == NULL)
2739 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 if ((portnr < 0) || (portnr >= panelp->nrports))
Jiri Slaby615e4a72006-12-08 02:38:38 -08002741 return(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 return(panelp->ports[portnr]);
2743}
2744
2745/*****************************************************************************/
2746
2747/*
2748 * Return the port stats structure to user app. A NULL port struct
2749 * pointer passed in means that we need to find out from the app
2750 * what port to get stats for (used through board control device).
2751 */
2752
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002753static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754{
2755 unsigned char *head, *tail;
2756 unsigned long flags;
2757
2758 if (!portp) {
2759 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2760 return -EFAULT;
2761 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2762 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002763 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return(-ENODEV);
2765 }
2766
2767 portp->stats.state = portp->istate;
2768 portp->stats.flags = portp->flags;
2769 portp->stats.hwid = portp->hwid;
2770
2771 portp->stats.ttystate = 0;
2772 portp->stats.cflags = 0;
2773 portp->stats.iflags = 0;
2774 portp->stats.oflags = 0;
2775 portp->stats.lflags = 0;
2776 portp->stats.rxbuffered = 0;
2777
Alan Coxb65b5b52006-06-27 02:54:05 -07002778 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002779 if (portp->tty != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 if (portp->tty->driver_data == portp) {
2781 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002782 /* No longer available as a statistic */
2783 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002784 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 portp->stats.cflags = portp->tty->termios->c_cflag;
2786 portp->stats.iflags = portp->tty->termios->c_iflag;
2787 portp->stats.oflags = portp->tty->termios->c_oflag;
2788 portp->stats.lflags = portp->tty->termios->c_lflag;
2789 }
2790 }
2791 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002792 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
2794 head = portp->tx.head;
2795 tail = portp->tx.tail;
2796 portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
2797 (STL_TXBUFSIZE - (tail - head)));
2798
2799 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2800
2801 return copy_to_user(cp, &portp->stats,
2802 sizeof(comstats_t)) ? -EFAULT : 0;
2803}
2804
2805/*****************************************************************************/
2806
2807/*
2808 * Clear the port stats structure. We also return it zeroed out...
2809 */
2810
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002811static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
2813 if (!portp) {
2814 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2815 return -EFAULT;
2816 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2817 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002818 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return(-ENODEV);
2820 }
2821
2822 memset(&portp->stats, 0, sizeof(comstats_t));
2823 portp->stats.brd = portp->brdnr;
2824 portp->stats.panel = portp->panelnr;
2825 portp->stats.port = portp->portnr;
2826 return copy_to_user(cp, &portp->stats,
2827 sizeof(comstats_t)) ? -EFAULT : 0;
2828}
2829
2830/*****************************************************************************/
2831
2832/*
2833 * Return the entire driver ports structure to a user app.
2834 */
2835
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002836static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002838 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002840 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 return -EFAULT;
2842 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2843 stl_dummyport.portnr);
2844 if (!portp)
2845 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002846 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847}
2848
2849/*****************************************************************************/
2850
2851/*
2852 * Return the entire driver board structure to a user app.
2853 */
2854
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002855static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002857 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002859 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 return -EFAULT;
2861 if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
2862 return -ENODEV;
2863 brdp = stl_brds[stl_dummybrd.brdnr];
2864 if (!brdp)
2865 return(-ENODEV);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002866 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867}
2868
2869/*****************************************************************************/
2870
2871/*
2872 * The "staliomem" device is also required to do some special operations
2873 * on the board and/or ports. In this driver it is mostly used for stats
2874 * collection.
2875 */
2876
2877static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2878{
2879 int brdnr, rc;
2880 void __user *argp = (void __user *)arg;
2881
Jiri Slabya0564e12006-12-08 02:38:37 -08002882 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884 brdnr = iminor(ip);
2885 if (brdnr >= STL_MAXBRDS)
2886 return(-ENODEV);
2887 rc = 0;
2888
2889 switch (cmd) {
2890 case COM_GETPORTSTATS:
2891 rc = stl_getportstats(NULL, argp);
2892 break;
2893 case COM_CLRPORTSTATS:
2894 rc = stl_clrportstats(NULL, argp);
2895 break;
2896 case COM_GETBRDSTATS:
2897 rc = stl_getbrdstats(argp);
2898 break;
2899 case COM_READPORT:
2900 rc = stl_getportstruct(argp);
2901 break;
2902 case COM_READBOARD:
2903 rc = stl_getbrdstruct(argp);
2904 break;
2905 default:
2906 rc = -ENOIOCTLCMD;
2907 break;
2908 }
2909
2910 return(rc);
2911}
2912
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002913static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 .open = stl_open,
2915 .close = stl_close,
2916 .write = stl_write,
2917 .put_char = stl_putchar,
2918 .flush_chars = stl_flushchars,
2919 .write_room = stl_writeroom,
2920 .chars_in_buffer = stl_charsinbuffer,
2921 .ioctl = stl_ioctl,
2922 .set_termios = stl_settermios,
2923 .throttle = stl_throttle,
2924 .unthrottle = stl_unthrottle,
2925 .stop = stl_stop,
2926 .start = stl_start,
2927 .hangup = stl_hangup,
2928 .flush_buffer = stl_flushbuffer,
2929 .break_ctl = stl_breakctl,
2930 .wait_until_sent = stl_waituntilsent,
2931 .send_xchar = stl_sendxchar,
2932 .read_proc = stl_readproc,
2933 .tiocmget = stl_tiocmget,
2934 .tiocmset = stl_tiocmset,
2935};
2936
2937/*****************************************************************************/
2938
Adrian Bunk408b6642005-05-01 08:59:29 -07002939static int __init stl_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
2941 int i;
2942 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
2943
Alan Coxeffc8b72006-06-28 04:26:51 -07002944 spin_lock_init(&stallion_lock);
2945 spin_lock_init(&brd_lock);
2946
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947 stl_initbrds();
2948
2949 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
2950 if (!stl_serial)
2951 return -1;
2952
2953/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 * Set up a character driver for per board stuff. This is mainly used
2955 * to do stats ioctls on the ports.
2956 */
2957 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
2958 printk("STALLION: failed to register serial board device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959
gregkh@suse.deca8eca62005-03-23 09:53:09 -08002960 stallion_class = class_create(THIS_MODULE, "staliomem");
Greg Kroah-Hartman7c69ef72005-06-20 21:15:16 -07002961 for (i = 0; i < 4; i++)
Greg Kroah-Hartman53f46542005-10-27 22:25:43 -07002962 class_device_create(stallion_class, NULL,
2963 MKDEV(STL_SIOMEMMAJOR, i), NULL,
2964 "staliomem%d", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965
2966 stl_serial->owner = THIS_MODULE;
2967 stl_serial->driver_name = stl_drvname;
2968 stl_serial->name = "ttyE";
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 stl_serial->major = STL_SERIALMAJOR;
2970 stl_serial->minor_start = 0;
2971 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
2972 stl_serial->subtype = SERIAL_TYPE_NORMAL;
2973 stl_serial->init_termios = stl_deftermios;
2974 stl_serial->flags = TTY_DRIVER_REAL_RAW;
2975 tty_set_operations(stl_serial, &stl_ops);
2976
2977 if (tty_register_driver(stl_serial)) {
2978 put_tty_driver(stl_serial);
2979 printk("STALLION: failed to register serial driver\n");
2980 return -1;
2981 }
2982
Jesper Juhl014c2542006-01-15 02:37:08 +01002983 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984}
2985
2986/*****************************************************************************/
2987/* CD1400 HARDWARE FUNCTIONS */
2988/*****************************************************************************/
2989
2990/*
2991 * These functions get/set/update the registers of the cd1400 UARTs.
2992 * Access to the cd1400 registers is via an address/data io port pair.
2993 * (Maybe should make this inline...)
2994 */
2995
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002996static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997{
2998 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002999 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000}
3001
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003002static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003{
3004 outb((regnr + portp->uartaddr), portp->ioaddr);
3005 outb(value, portp->ioaddr + EREG_DATA);
3006}
3007
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003008static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009{
3010 outb((regnr + portp->uartaddr), portp->ioaddr);
3011 if (inb(portp->ioaddr + EREG_DATA) != value) {
3012 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01003013 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003015 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016}
3017
3018/*****************************************************************************/
3019
3020/*
3021 * Inbitialize the UARTs in a panel. We don't care what sort of board
3022 * these ports are on - since the port io registers are almost
3023 * identical when dealing with ports.
3024 */
3025
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003026static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027{
3028 unsigned int gfrcr;
3029 int chipmask, i, j;
3030 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003031 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032
Jiri Slabya0564e12006-12-08 02:38:37 -08003033 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
Alan Coxb65b5b52006-06-27 02:54:05 -07003035 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 BRDENABLE(panelp->brdnr, panelp->pagenr);
3037
3038/*
3039 * Check that each chip is present and started up OK.
3040 */
3041 chipmask = 0;
3042 nrchips = panelp->nrports / CD1400_PORTS;
3043 for (i = 0; (i < nrchips); i++) {
3044 if (brdp->brdtype == BRD_ECHPCI) {
3045 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
3046 ioaddr = panelp->iobase;
3047 } else {
3048 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
3049 }
3050 uartaddr = (i & 0x01) ? 0x080 : 0;
3051 outb((GFRCR + uartaddr), ioaddr);
3052 outb(0, (ioaddr + EREG_DATA));
3053 outb((CCR + uartaddr), ioaddr);
3054 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
3055 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
3056 outb((GFRCR + uartaddr), ioaddr);
3057 for (j = 0; (j < CCR_MAXWAIT); j++) {
3058 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
3059 break;
3060 }
3061 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
3062 printk("STALLION: cd1400 not responding, "
3063 "brd=%d panel=%d chip=%d\n",
3064 panelp->brdnr, panelp->panelnr, i);
3065 continue;
3066 }
3067 chipmask |= (0x1 << i);
3068 outb((PPR + uartaddr), ioaddr);
3069 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
3070 }
3071
3072 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003073 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01003074 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075}
3076
3077/*****************************************************************************/
3078
3079/*
3080 * Initialize hardware specific port registers.
3081 */
3082
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003083static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
Alan Coxb65b5b52006-06-27 02:54:05 -07003085 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08003086 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3087 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088
Jiri Slaby615e4a72006-12-08 02:38:38 -08003089 if ((brdp == NULL) || (panelp == NULL) ||
3090 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 return;
3092
Alan Coxb65b5b52006-06-27 02:54:05 -07003093 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
3095 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
3096 portp->uartaddr = (portp->portnr & 0x04) << 5;
3097 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
3098
3099 BRDENABLE(portp->brdnr, portp->pagenr);
3100 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3101 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
3102 portp->hwid = stl_cd1400getreg(portp, GFRCR);
3103 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003104 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105}
3106
3107/*****************************************************************************/
3108
3109/*
3110 * Wait for the command register to be ready. We will poll this,
3111 * since it won't usually take too long to be ready.
3112 */
3113
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003114static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115{
3116 int i;
3117
3118 for (i = 0; (i < CCR_MAXWAIT); i++) {
3119 if (stl_cd1400getreg(portp, CCR) == 0) {
3120 return;
3121 }
3122 }
3123
3124 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
3125 portp->portnr, portp->panelnr, portp->brdnr);
3126}
3127
3128/*****************************************************************************/
3129
3130/*
3131 * Set up the cd1400 registers for a port based on the termios port
3132 * settings.
3133 */
3134
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003135static void stl_cd1400setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003137 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 unsigned long flags;
3139 unsigned int clkdiv, baudrate;
3140 unsigned char cor1, cor2, cor3;
3141 unsigned char cor4, cor5, ccr;
3142 unsigned char srer, sreron, sreroff;
3143 unsigned char mcor1, mcor2, rtpr;
3144 unsigned char clk, div;
3145
3146 cor1 = 0;
3147 cor2 = 0;
3148 cor3 = 0;
3149 cor4 = 0;
3150 cor5 = 0;
3151 ccr = 0;
3152 rtpr = 0;
3153 clk = 0;
3154 div = 0;
3155 mcor1 = 0;
3156 mcor2 = 0;
3157 sreron = 0;
3158 sreroff = 0;
3159
3160 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003161 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162 return;
3163
3164/*
3165 * Set up the RX char ignore mask with those RX error types we
3166 * can ignore. We can get the cd1400 to help us out a little here,
3167 * it will ignore parity errors and breaks for us.
3168 */
3169 portp->rxignoremsk = 0;
3170 if (tiosp->c_iflag & IGNPAR) {
3171 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
3172 cor1 |= COR1_PARIGNORE;
3173 }
3174 if (tiosp->c_iflag & IGNBRK) {
3175 portp->rxignoremsk |= ST_BREAK;
3176 cor4 |= COR4_IGNBRK;
3177 }
3178
3179 portp->rxmarkmsk = ST_OVERRUN;
3180 if (tiosp->c_iflag & (INPCK | PARMRK))
3181 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
3182 if (tiosp->c_iflag & BRKINT)
3183 portp->rxmarkmsk |= ST_BREAK;
3184
3185/*
3186 * Go through the char size, parity and stop bits and set all the
3187 * option register appropriately.
3188 */
3189 switch (tiosp->c_cflag & CSIZE) {
3190 case CS5:
3191 cor1 |= COR1_CHL5;
3192 break;
3193 case CS6:
3194 cor1 |= COR1_CHL6;
3195 break;
3196 case CS7:
3197 cor1 |= COR1_CHL7;
3198 break;
3199 default:
3200 cor1 |= COR1_CHL8;
3201 break;
3202 }
3203
3204 if (tiosp->c_cflag & CSTOPB)
3205 cor1 |= COR1_STOP2;
3206 else
3207 cor1 |= COR1_STOP1;
3208
3209 if (tiosp->c_cflag & PARENB) {
3210 if (tiosp->c_cflag & PARODD)
3211 cor1 |= (COR1_PARENB | COR1_PARODD);
3212 else
3213 cor1 |= (COR1_PARENB | COR1_PAREVEN);
3214 } else {
3215 cor1 |= COR1_PARNONE;
3216 }
3217
3218/*
3219 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
3220 * space for hardware flow control and the like. This should be set to
3221 * VMIN. Also here we will set the RX data timeout to 10ms - this should
3222 * really be based on VTIME.
3223 */
3224 cor3 |= FIFO_RXTHRESHOLD;
3225 rtpr = 2;
3226
3227/*
3228 * Calculate the baud rate timers. For now we will just assume that
3229 * the input and output baud are the same. Could have used a baud
3230 * table here, but this way we can generate virtually any baud rate
3231 * we like!
3232 */
3233 baudrate = tiosp->c_cflag & CBAUD;
3234 if (baudrate & CBAUDEX) {
3235 baudrate &= ~CBAUDEX;
3236 if ((baudrate < 1) || (baudrate > 4))
3237 tiosp->c_cflag &= ~CBAUDEX;
3238 else
3239 baudrate += 15;
3240 }
3241 baudrate = stl_baudrates[baudrate];
3242 if ((tiosp->c_cflag & CBAUD) == B38400) {
3243 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3244 baudrate = 57600;
3245 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3246 baudrate = 115200;
3247 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3248 baudrate = 230400;
3249 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3250 baudrate = 460800;
3251 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3252 baudrate = (portp->baud_base / portp->custom_divisor);
3253 }
3254 if (baudrate > STL_CD1400MAXBAUD)
3255 baudrate = STL_CD1400MAXBAUD;
3256
3257 if (baudrate > 0) {
3258 for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
3259 clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
3260 if (clkdiv < 0x100)
3261 break;
3262 }
3263 div = (unsigned char) clkdiv;
3264 }
3265
3266/*
3267 * Check what form of modem signaling is required and set it up.
3268 */
3269 if ((tiosp->c_cflag & CLOCAL) == 0) {
3270 mcor1 |= MCOR1_DCD;
3271 mcor2 |= MCOR2_DCD;
3272 sreron |= SRER_MODEM;
3273 portp->flags |= ASYNC_CHECK_CD;
3274 } else {
3275 portp->flags &= ~ASYNC_CHECK_CD;
3276 }
3277
3278/*
3279 * Setup cd1400 enhanced modes if we can. In particular we want to
3280 * handle as much of the flow control as possible automatically. As
3281 * well as saving a few CPU cycles it will also greatly improve flow
3282 * control reliability.
3283 */
3284 if (tiosp->c_iflag & IXON) {
3285 cor2 |= COR2_TXIBE;
3286 cor3 |= COR3_SCD12;
3287 if (tiosp->c_iflag & IXANY)
3288 cor2 |= COR2_IXM;
3289 }
3290
3291 if (tiosp->c_cflag & CRTSCTS) {
3292 cor2 |= COR2_CTSAE;
3293 mcor1 |= FIFO_RTSTHRESHOLD;
3294 }
3295
3296/*
3297 * All cd1400 register values calculated so go through and set
3298 * them all up.
3299 */
3300
Jiri Slabya0564e12006-12-08 02:38:37 -08003301 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003303 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003305 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003307 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3308 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3310 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Alan Coxb65b5b52006-06-27 02:54:05 -07003312 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 BRDENABLE(portp->brdnr, portp->pagenr);
3314 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3315 srer = stl_cd1400getreg(portp, SRER);
3316 stl_cd1400setreg(portp, SRER, 0);
3317 if (stl_cd1400updatereg(portp, COR1, cor1))
3318 ccr = 1;
3319 if (stl_cd1400updatereg(portp, COR2, cor2))
3320 ccr = 1;
3321 if (stl_cd1400updatereg(portp, COR3, cor3))
3322 ccr = 1;
3323 if (ccr) {
3324 stl_cd1400ccrwait(portp);
3325 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3326 }
3327 stl_cd1400setreg(portp, COR4, cor4);
3328 stl_cd1400setreg(portp, COR5, cor5);
3329 stl_cd1400setreg(portp, MCOR1, mcor1);
3330 stl_cd1400setreg(portp, MCOR2, mcor2);
3331 if (baudrate > 0) {
3332 stl_cd1400setreg(portp, TCOR, clk);
3333 stl_cd1400setreg(portp, TBPR, div);
3334 stl_cd1400setreg(portp, RCOR, clk);
3335 stl_cd1400setreg(portp, RBPR, div);
3336 }
3337 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3338 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3339 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3340 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3341 stl_cd1400setreg(portp, RTPR, rtpr);
3342 mcor1 = stl_cd1400getreg(portp, MSVR1);
3343 if (mcor1 & MSVR1_DCD)
3344 portp->sigs |= TIOCM_CD;
3345 else
3346 portp->sigs &= ~TIOCM_CD;
3347 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3348 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003349 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350}
3351
3352/*****************************************************************************/
3353
3354/*
3355 * Set the state of the DTR and RTS signals.
3356 */
3357
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003358static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359{
3360 unsigned char msvr1, msvr2;
3361 unsigned long flags;
3362
Jiri Slabya0564e12006-12-08 02:38:37 -08003363 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3364 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365
3366 msvr1 = 0;
3367 msvr2 = 0;
3368 if (dtr > 0)
3369 msvr1 = MSVR1_DTR;
3370 if (rts > 0)
3371 msvr2 = MSVR2_RTS;
3372
Alan Coxb65b5b52006-06-27 02:54:05 -07003373 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 BRDENABLE(portp->brdnr, portp->pagenr);
3375 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3376 if (rts >= 0)
3377 stl_cd1400setreg(portp, MSVR2, msvr2);
3378 if (dtr >= 0)
3379 stl_cd1400setreg(portp, MSVR1, msvr1);
3380 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003381 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382}
3383
3384/*****************************************************************************/
3385
3386/*
3387 * Return the state of the signals.
3388 */
3389
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003390static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391{
3392 unsigned char msvr1, msvr2;
3393 unsigned long flags;
3394 int sigs;
3395
Jiri Slabya0564e12006-12-08 02:38:37 -08003396 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397
Alan Coxb65b5b52006-06-27 02:54:05 -07003398 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 BRDENABLE(portp->brdnr, portp->pagenr);
3400 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3401 msvr1 = stl_cd1400getreg(portp, MSVR1);
3402 msvr2 = stl_cd1400getreg(portp, MSVR2);
3403 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003404 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
3406 sigs = 0;
3407 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3408 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3409 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3410 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3411#if 0
3412 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3413 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3414#else
3415 sigs |= TIOCM_DSR;
3416#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003417 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418}
3419
3420/*****************************************************************************/
3421
3422/*
3423 * Enable/Disable the Transmitter and/or Receiver.
3424 */
3425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003426static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
3428 unsigned char ccr;
3429 unsigned long flags;
3430
Jiri Slabya0564e12006-12-08 02:38:37 -08003431 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3432
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 ccr = 0;
3434
3435 if (tx == 0)
3436 ccr |= CCR_TXDISABLE;
3437 else if (tx > 0)
3438 ccr |= CCR_TXENABLE;
3439 if (rx == 0)
3440 ccr |= CCR_RXDISABLE;
3441 else if (rx > 0)
3442 ccr |= CCR_RXENABLE;
3443
Alan Coxb65b5b52006-06-27 02:54:05 -07003444 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445 BRDENABLE(portp->brdnr, portp->pagenr);
3446 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3447 stl_cd1400ccrwait(portp);
3448 stl_cd1400setreg(portp, CCR, ccr);
3449 stl_cd1400ccrwait(portp);
3450 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003451 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452}
3453
3454/*****************************************************************************/
3455
3456/*
3457 * Start/stop the Transmitter and/or Receiver.
3458 */
3459
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003460static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461{
3462 unsigned char sreron, sreroff;
3463 unsigned long flags;
3464
Jiri Slabya0564e12006-12-08 02:38:37 -08003465 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
3467 sreron = 0;
3468 sreroff = 0;
3469 if (tx == 0)
3470 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3471 else if (tx == 1)
3472 sreron |= SRER_TXDATA;
3473 else if (tx >= 2)
3474 sreron |= SRER_TXEMPTY;
3475 if (rx == 0)
3476 sreroff |= SRER_RXDATA;
3477 else if (rx > 0)
3478 sreron |= SRER_RXDATA;
3479
Alan Coxb65b5b52006-06-27 02:54:05 -07003480 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 BRDENABLE(portp->brdnr, portp->pagenr);
3482 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3483 stl_cd1400setreg(portp, SRER,
3484 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3485 BRDDISABLE(portp->brdnr);
3486 if (tx > 0)
3487 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003488 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489}
3490
3491/*****************************************************************************/
3492
3493/*
3494 * Disable all interrupts from this port.
3495 */
3496
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003497static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498{
3499 unsigned long flags;
3500
Jiri Slabya0564e12006-12-08 02:38:37 -08003501 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3502
Alan Coxb65b5b52006-06-27 02:54:05 -07003503 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 BRDENABLE(portp->brdnr, portp->pagenr);
3505 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3506 stl_cd1400setreg(portp, SRER, 0);
3507 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003508 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509}
3510
3511/*****************************************************************************/
3512
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003513static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514{
3515 unsigned long flags;
3516
Jiri Slabya0564e12006-12-08 02:38:37 -08003517 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518
Alan Coxb65b5b52006-06-27 02:54:05 -07003519 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 BRDENABLE(portp->brdnr, portp->pagenr);
3521 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3522 stl_cd1400setreg(portp, SRER,
3523 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3524 SRER_TXEMPTY));
3525 BRDDISABLE(portp->brdnr);
3526 portp->brklen = len;
3527 if (len == 1)
3528 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003529 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530}
3531
3532/*****************************************************************************/
3533
3534/*
3535 * Take flow control actions...
3536 */
3537
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003538static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539{
3540 struct tty_struct *tty;
3541 unsigned long flags;
3542
Jiri Slabya0564e12006-12-08 02:38:37 -08003543 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
Jiri Slaby615e4a72006-12-08 02:38:38 -08003545 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 return;
3547 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003548 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 return;
3550
Alan Coxb65b5b52006-06-27 02:54:05 -07003551 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 BRDENABLE(portp->brdnr, portp->pagenr);
3553 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3554
3555 if (state) {
3556 if (tty->termios->c_iflag & IXOFF) {
3557 stl_cd1400ccrwait(portp);
3558 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3559 portp->stats.rxxon++;
3560 stl_cd1400ccrwait(portp);
3561 }
3562/*
3563 * Question: should we return RTS to what it was before? It may
3564 * have been set by an ioctl... Suppose not, since if you have
3565 * hardware flow control set then it is pretty silly to go and
3566 * set the RTS line by hand.
3567 */
3568 if (tty->termios->c_cflag & CRTSCTS) {
3569 stl_cd1400setreg(portp, MCOR1,
3570 (stl_cd1400getreg(portp, MCOR1) |
3571 FIFO_RTSTHRESHOLD));
3572 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3573 portp->stats.rxrtson++;
3574 }
3575 } else {
3576 if (tty->termios->c_iflag & IXOFF) {
3577 stl_cd1400ccrwait(portp);
3578 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3579 portp->stats.rxxoff++;
3580 stl_cd1400ccrwait(portp);
3581 }
3582 if (tty->termios->c_cflag & CRTSCTS) {
3583 stl_cd1400setreg(portp, MCOR1,
3584 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3585 stl_cd1400setreg(portp, MSVR2, 0);
3586 portp->stats.rxrtsoff++;
3587 }
3588 }
3589
3590 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003591 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592}
3593
3594/*****************************************************************************/
3595
3596/*
3597 * Send a flow control character...
3598 */
3599
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003600static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601{
3602 struct tty_struct *tty;
3603 unsigned long flags;
3604
Jiri Slabya0564e12006-12-08 02:38:37 -08003605 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
Jiri Slaby615e4a72006-12-08 02:38:38 -08003607 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608 return;
3609 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003610 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 return;
3612
Alan Coxb65b5b52006-06-27 02:54:05 -07003613 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 BRDENABLE(portp->brdnr, portp->pagenr);
3615 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3616 if (state) {
3617 stl_cd1400ccrwait(portp);
3618 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3619 portp->stats.rxxon++;
3620 stl_cd1400ccrwait(portp);
3621 } else {
3622 stl_cd1400ccrwait(portp);
3623 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3624 portp->stats.rxxoff++;
3625 stl_cd1400ccrwait(portp);
3626 }
3627 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003628 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629}
3630
3631/*****************************************************************************/
3632
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003633static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634{
3635 unsigned long flags;
3636
Jiri Slabya0564e12006-12-08 02:38:37 -08003637 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Jiri Slaby615e4a72006-12-08 02:38:38 -08003639 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 return;
3641
Alan Coxb65b5b52006-06-27 02:54:05 -07003642 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 BRDENABLE(portp->brdnr, portp->pagenr);
3644 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3645 stl_cd1400ccrwait(portp);
3646 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3647 stl_cd1400ccrwait(portp);
3648 portp->tx.tail = portp->tx.head;
3649 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003650 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651}
3652
3653/*****************************************************************************/
3654
3655/*
3656 * Return the current state of data flow on this port. This is only
3657 * really interresting when determining if data has fully completed
3658 * transmission or not... This is easy for the cd1400, it accurately
3659 * maintains the busy port flag.
3660 */
3661
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003662static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663{
Jiri Slabya0564e12006-12-08 02:38:37 -08003664 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665
Jiri Slaby615e4a72006-12-08 02:38:38 -08003666 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003667 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Jesper Juhl014c2542006-01-15 02:37:08 +01003669 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670}
3671
3672/*****************************************************************************/
3673
3674/*
3675 * Interrupt service routine for cd1400 EasyIO boards.
3676 */
3677
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003678static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679{
3680 unsigned char svrtype;
3681
Jiri Slabya0564e12006-12-08 02:38:37 -08003682 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
Alan Coxb65b5b52006-06-27 02:54:05 -07003684 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 outb(SVRR, iobase);
3686 svrtype = inb(iobase + EREG_DATA);
3687 if (panelp->nrports > 4) {
3688 outb((SVRR + 0x80), iobase);
3689 svrtype |= inb(iobase + EREG_DATA);
3690 }
3691
3692 if (svrtype & SVRR_RX)
3693 stl_cd1400rxisr(panelp, iobase);
3694 else if (svrtype & SVRR_TX)
3695 stl_cd1400txisr(panelp, iobase);
3696 else if (svrtype & SVRR_MDM)
3697 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003698
3699 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700}
3701
3702/*****************************************************************************/
3703
3704/*
3705 * Interrupt service routine for cd1400 panels.
3706 */
3707
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003708static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709{
3710 unsigned char svrtype;
3711
Jiri Slabya0564e12006-12-08 02:38:37 -08003712 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713
3714 outb(SVRR, iobase);
3715 svrtype = inb(iobase + EREG_DATA);
3716 outb((SVRR + 0x80), iobase);
3717 svrtype |= inb(iobase + EREG_DATA);
3718 if (svrtype & SVRR_RX)
3719 stl_cd1400rxisr(panelp, iobase);
3720 else if (svrtype & SVRR_TX)
3721 stl_cd1400txisr(panelp, iobase);
3722 else if (svrtype & SVRR_MDM)
3723 stl_cd1400mdmisr(panelp, iobase);
3724}
3725
3726
3727/*****************************************************************************/
3728
3729/*
3730 * Unfortunately we need to handle breaks in the TX data stream, since
3731 * this is the only way to generate them on the cd1400.
3732 */
3733
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003734static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735{
3736 if (portp->brklen == 1) {
3737 outb((COR2 + portp->uartaddr), ioaddr);
3738 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3739 (ioaddr + EREG_DATA));
3740 outb((TDR + portp->uartaddr), ioaddr);
3741 outb(ETC_CMD, (ioaddr + EREG_DATA));
3742 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3743 outb((SRER + portp->uartaddr), ioaddr);
3744 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3745 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003746 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 } else if (portp->brklen > 1) {
3748 outb((TDR + portp->uartaddr), ioaddr);
3749 outb(ETC_CMD, (ioaddr + EREG_DATA));
3750 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3751 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003752 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753 } else {
3754 outb((COR2 + portp->uartaddr), ioaddr);
3755 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3756 (ioaddr + EREG_DATA));
3757 portp->brklen = 0;
3758 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003759 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760}
3761
3762/*****************************************************************************/
3763
3764/*
3765 * Transmit interrupt handler. This has gotta be fast! Handling TX
3766 * chars is pretty simple, stuff as many as possible from the TX buffer
3767 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3768 * are embedded as commands in the data stream. Oh no, had to use a goto!
3769 * This could be optimized more, will do when I get time...
3770 * In practice it is possible that interrupts are enabled but that the
3771 * port has been hung up. Need to handle not having any TX buffer here,
3772 * this is done by using the side effect that head and tail will also
3773 * be NULL if the buffer has been freed.
3774 */
3775
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003776static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003778 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 int len, stlen;
3780 char *head, *tail;
3781 unsigned char ioack, srer;
3782
Jiri Slabya0564e12006-12-08 02:38:37 -08003783 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784
3785 ioack = inb(ioaddr + EREG_TXACK);
3786 if (((ioack & panelp->ackmask) != 0) ||
3787 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3788 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3789 return;
3790 }
3791 portp = panelp->ports[(ioack >> 3)];
3792
3793/*
3794 * Unfortunately we need to handle breaks in the data stream, since
3795 * this is the only way to generate them on the cd1400. Do it now if
3796 * a break is to be sent.
3797 */
3798 if (portp->brklen != 0)
3799 if (stl_cd1400breakisr(portp, ioaddr))
3800 goto stl_txalldone;
3801
3802 head = portp->tx.head;
3803 tail = portp->tx.tail;
3804 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3805 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3806 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3807 set_bit(ASYI_TXLOW, &portp->istate);
3808 schedule_work(&portp->tqueue);
3809 }
3810
3811 if (len == 0) {
3812 outb((SRER + portp->uartaddr), ioaddr);
3813 srer = inb(ioaddr + EREG_DATA);
3814 if (srer & SRER_TXDATA) {
3815 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3816 } else {
3817 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3818 clear_bit(ASYI_TXBUSY, &portp->istate);
3819 }
3820 outb(srer, (ioaddr + EREG_DATA));
3821 } else {
3822 len = MIN(len, CD1400_TXFIFOSIZE);
3823 portp->stats.txtotal += len;
3824 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
3825 outb((TDR + portp->uartaddr), ioaddr);
3826 outsb((ioaddr + EREG_DATA), tail, stlen);
3827 len -= stlen;
3828 tail += stlen;
3829 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3830 tail = portp->tx.buf;
3831 if (len > 0) {
3832 outsb((ioaddr + EREG_DATA), tail, len);
3833 tail += len;
3834 }
3835 portp->tx.tail = tail;
3836 }
3837
3838stl_txalldone:
3839 outb((EOSRR + portp->uartaddr), ioaddr);
3840 outb(0, (ioaddr + EREG_DATA));
3841}
3842
3843/*****************************************************************************/
3844
3845/*
3846 * Receive character interrupt handler. Determine if we have good chars
3847 * or bad chars and then process appropriately. Good chars are easy
3848 * just shove the lot into the RX buffer and set all status byte to 0.
3849 * If a bad RX char then process as required. This routine needs to be
3850 * fast! In practice it is possible that we get an interrupt on a port
3851 * that is closed. This can happen on hangups - since they completely
3852 * shutdown a port not in user context. Need to handle this case.
3853 */
3854
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003855static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003857 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 struct tty_struct *tty;
3859 unsigned int ioack, len, buflen;
3860 unsigned char status;
3861 char ch;
3862
Jiri Slabya0564e12006-12-08 02:38:37 -08003863 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865 ioack = inb(ioaddr + EREG_RXACK);
3866 if ((ioack & panelp->ackmask) != 0) {
3867 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3868 return;
3869 }
3870 portp = panelp->ports[(ioack >> 3)];
3871 tty = portp->tty;
3872
3873 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3874 outb((RDCR + portp->uartaddr), ioaddr);
3875 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003876 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 len = MIN(len, sizeof(stl_unwanted));
3878 outb((RDSR + portp->uartaddr), ioaddr);
3879 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3880 portp->stats.rxlost += len;
3881 portp->stats.rxtotal += len;
3882 } else {
3883 len = MIN(len, buflen);
3884 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003885 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003887 tty_prepare_flip_string(tty, &ptr, len);
3888 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 tty_schedule_flip(tty);
3890 portp->stats.rxtotal += len;
3891 }
3892 }
3893 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3894 outb((RDSR + portp->uartaddr), ioaddr);
3895 status = inb(ioaddr + EREG_DATA);
3896 ch = inb(ioaddr + EREG_DATA);
3897 if (status & ST_PARITY)
3898 portp->stats.rxparity++;
3899 if (status & ST_FRAMING)
3900 portp->stats.rxframing++;
3901 if (status & ST_OVERRUN)
3902 portp->stats.rxoverrun++;
3903 if (status & ST_BREAK)
3904 portp->stats.rxbreaks++;
3905 if (status & ST_SCHARMASK) {
3906 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3907 portp->stats.txxon++;
3908 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3909 portp->stats.txxoff++;
3910 goto stl_rxalldone;
3911 }
Alan Cox33f0f882006-01-09 20:54:13 -08003912 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 if (portp->rxmarkmsk & status) {
3914 if (status & ST_BREAK) {
3915 status = TTY_BREAK;
3916 if (portp->flags & ASYNC_SAK) {
3917 do_SAK(tty);
3918 BRDENABLE(portp->brdnr, portp->pagenr);
3919 }
3920 } else if (status & ST_PARITY) {
3921 status = TTY_PARITY;
3922 } else if (status & ST_FRAMING) {
3923 status = TTY_FRAME;
3924 } else if(status & ST_OVERRUN) {
3925 status = TTY_OVERRUN;
3926 } else {
3927 status = 0;
3928 }
3929 } else {
3930 status = 0;
3931 }
Alan Cox33f0f882006-01-09 20:54:13 -08003932 tty_insert_flip_char(tty, ch, status);
3933 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 }
3935 } else {
3936 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3937 return;
3938 }
3939
3940stl_rxalldone:
3941 outb((EOSRR + portp->uartaddr), ioaddr);
3942 outb(0, (ioaddr + EREG_DATA));
3943}
3944
3945/*****************************************************************************/
3946
3947/*
3948 * Modem interrupt handler. The is called when the modem signal line
3949 * (DCD) has changed state. Leave most of the work to the off-level
3950 * processing routine.
3951 */
3952
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003953static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003955 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 unsigned int ioack;
3957 unsigned char misr;
3958
Jiri Slabya0564e12006-12-08 02:38:37 -08003959 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960
3961 ioack = inb(ioaddr + EREG_MDACK);
3962 if (((ioack & panelp->ackmask) != 0) ||
3963 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3964 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3965 return;
3966 }
3967 portp = panelp->ports[(ioack >> 3)];
3968
3969 outb((MISR + portp->uartaddr), ioaddr);
3970 misr = inb(ioaddr + EREG_DATA);
3971 if (misr & MISR_DCD) {
3972 set_bit(ASYI_DCDCHANGE, &portp->istate);
3973 schedule_work(&portp->tqueue);
3974 portp->stats.modem++;
3975 }
3976
3977 outb((EOSRR + portp->uartaddr), ioaddr);
3978 outb(0, (ioaddr + EREG_DATA));
3979}
3980
3981/*****************************************************************************/
3982/* SC26198 HARDWARE FUNCTIONS */
3983/*****************************************************************************/
3984
3985/*
3986 * These functions get/set/update the registers of the sc26198 UARTs.
3987 * Access to the sc26198 registers is via an address/data io port pair.
3988 * (Maybe should make this inline...)
3989 */
3990
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003991static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992{
3993 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003994 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995}
3996
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003997static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998{
3999 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
4000 outb(value, (portp->ioaddr + XP_DATA));
4001}
4002
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004003static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004{
4005 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
4006 if (inb(portp->ioaddr + XP_DATA) != value) {
4007 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01004008 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 }
Jesper Juhl014c2542006-01-15 02:37:08 +01004010 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011}
4012
4013/*****************************************************************************/
4014
4015/*
4016 * Functions to get and set the sc26198 global registers.
4017 */
4018
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004019static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020{
4021 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01004022 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023}
4024
4025#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004026static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027{
4028 outb(regnr, (portp->ioaddr + XP_ADDR));
4029 outb(value, (portp->ioaddr + XP_DATA));
4030}
4031#endif
4032
4033/*****************************************************************************/
4034
4035/*
4036 * Inbitialize the UARTs in a panel. We don't care what sort of board
4037 * these ports are on - since the port io registers are almost
4038 * identical when dealing with ports.
4039 */
4040
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004041static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042{
4043 int chipmask, i;
4044 int nrchips, ioaddr;
4045
Jiri Slabya0564e12006-12-08 02:38:37 -08004046 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
4048 BRDENABLE(panelp->brdnr, panelp->pagenr);
4049
4050/*
4051 * Check that each chip is present and started up OK.
4052 */
4053 chipmask = 0;
4054 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
4055 if (brdp->brdtype == BRD_ECHPCI)
4056 outb(panelp->pagenr, brdp->ioctrl);
4057
4058 for (i = 0; (i < nrchips); i++) {
4059 ioaddr = panelp->iobase + (i * 4);
4060 outb(SCCR, (ioaddr + XP_ADDR));
4061 outb(CR_RESETALL, (ioaddr + XP_DATA));
4062 outb(TSTR, (ioaddr + XP_ADDR));
4063 if (inb(ioaddr + XP_DATA) != 0) {
4064 printk("STALLION: sc26198 not responding, "
4065 "brd=%d panel=%d chip=%d\n",
4066 panelp->brdnr, panelp->panelnr, i);
4067 continue;
4068 }
4069 chipmask |= (0x1 << i);
4070 outb(GCCR, (ioaddr + XP_ADDR));
4071 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
4072 outb(WDTRCR, (ioaddr + XP_ADDR));
4073 outb(0xff, (ioaddr + XP_DATA));
4074 }
4075
4076 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01004077 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078}
4079
4080/*****************************************************************************/
4081
4082/*
4083 * Initialize hardware specific port registers.
4084 */
4085
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004086static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087{
Jiri Slabya0564e12006-12-08 02:38:37 -08004088 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
4089 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Jiri Slaby615e4a72006-12-08 02:38:38 -08004091 if ((brdp == NULL) || (panelp == NULL) ||
4092 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093 return;
4094
4095 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
4096 portp->uartaddr = (portp->portnr & 0x07) << 4;
4097 portp->pagenr = panelp->pagenr;
4098 portp->hwid = 0x1;
4099
4100 BRDENABLE(portp->brdnr, portp->pagenr);
4101 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
4102 BRDDISABLE(portp->brdnr);
4103}
4104
4105/*****************************************************************************/
4106
4107/*
4108 * Set up the sc26198 registers for a port based on the termios port
4109 * settings.
4110 */
4111
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004112static void stl_sc26198setport(struct stlport *portp, struct termios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004114 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 unsigned long flags;
4116 unsigned int baudrate;
4117 unsigned char mr0, mr1, mr2, clk;
4118 unsigned char imron, imroff, iopr, ipr;
4119
4120 mr0 = 0;
4121 mr1 = 0;
4122 mr2 = 0;
4123 clk = 0;
4124 iopr = 0;
4125 imron = 0;
4126 imroff = 0;
4127
4128 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08004129 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 return;
4131
4132/*
4133 * Set up the RX char ignore mask with those RX error types we
4134 * can ignore.
4135 */
4136 portp->rxignoremsk = 0;
4137 if (tiosp->c_iflag & IGNPAR)
4138 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
4139 SR_RXOVERRUN);
4140 if (tiosp->c_iflag & IGNBRK)
4141 portp->rxignoremsk |= SR_RXBREAK;
4142
4143 portp->rxmarkmsk = SR_RXOVERRUN;
4144 if (tiosp->c_iflag & (INPCK | PARMRK))
4145 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
4146 if (tiosp->c_iflag & BRKINT)
4147 portp->rxmarkmsk |= SR_RXBREAK;
4148
4149/*
4150 * Go through the char size, parity and stop bits and set all the
4151 * option register appropriately.
4152 */
4153 switch (tiosp->c_cflag & CSIZE) {
4154 case CS5:
4155 mr1 |= MR1_CS5;
4156 break;
4157 case CS6:
4158 mr1 |= MR1_CS6;
4159 break;
4160 case CS7:
4161 mr1 |= MR1_CS7;
4162 break;
4163 default:
4164 mr1 |= MR1_CS8;
4165 break;
4166 }
4167
4168 if (tiosp->c_cflag & CSTOPB)
4169 mr2 |= MR2_STOP2;
4170 else
4171 mr2 |= MR2_STOP1;
4172
4173 if (tiosp->c_cflag & PARENB) {
4174 if (tiosp->c_cflag & PARODD)
4175 mr1 |= (MR1_PARENB | MR1_PARODD);
4176 else
4177 mr1 |= (MR1_PARENB | MR1_PAREVEN);
4178 } else {
4179 mr1 |= MR1_PARNONE;
4180 }
4181
4182 mr1 |= MR1_ERRBLOCK;
4183
4184/*
4185 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
4186 * space for hardware flow control and the like. This should be set to
4187 * VMIN.
4188 */
4189 mr2 |= MR2_RXFIFOHALF;
4190
4191/*
4192 * Calculate the baud rate timers. For now we will just assume that
4193 * the input and output baud are the same. The sc26198 has a fixed
4194 * baud rate table, so only discrete baud rates possible.
4195 */
4196 baudrate = tiosp->c_cflag & CBAUD;
4197 if (baudrate & CBAUDEX) {
4198 baudrate &= ~CBAUDEX;
4199 if ((baudrate < 1) || (baudrate > 4))
4200 tiosp->c_cflag &= ~CBAUDEX;
4201 else
4202 baudrate += 15;
4203 }
4204 baudrate = stl_baudrates[baudrate];
4205 if ((tiosp->c_cflag & CBAUD) == B38400) {
4206 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
4207 baudrate = 57600;
4208 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
4209 baudrate = 115200;
4210 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
4211 baudrate = 230400;
4212 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
4213 baudrate = 460800;
4214 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
4215 baudrate = (portp->baud_base / portp->custom_divisor);
4216 }
4217 if (baudrate > STL_SC26198MAXBAUD)
4218 baudrate = STL_SC26198MAXBAUD;
4219
4220 if (baudrate > 0) {
4221 for (clk = 0; (clk < SC26198_NRBAUDS); clk++) {
4222 if (baudrate <= sc26198_baudtable[clk])
4223 break;
4224 }
4225 }
4226
4227/*
4228 * Check what form of modem signaling is required and set it up.
4229 */
4230 if (tiosp->c_cflag & CLOCAL) {
4231 portp->flags &= ~ASYNC_CHECK_CD;
4232 } else {
4233 iopr |= IOPR_DCDCOS;
4234 imron |= IR_IOPORT;
4235 portp->flags |= ASYNC_CHECK_CD;
4236 }
4237
4238/*
4239 * Setup sc26198 enhanced modes if we can. In particular we want to
4240 * handle as much of the flow control as possible automatically. As
4241 * well as saving a few CPU cycles it will also greatly improve flow
4242 * control reliability.
4243 */
4244 if (tiosp->c_iflag & IXON) {
4245 mr0 |= MR0_SWFTX | MR0_SWFT;
4246 imron |= IR_XONXOFF;
4247 } else {
4248 imroff |= IR_XONXOFF;
4249 }
4250 if (tiosp->c_iflag & IXOFF)
4251 mr0 |= MR0_SWFRX;
4252
4253 if (tiosp->c_cflag & CRTSCTS) {
4254 mr2 |= MR2_AUTOCTS;
4255 mr1 |= MR1_AUTORTS;
4256 }
4257
4258/*
4259 * All sc26198 register values calculated so go through and set
4260 * them all up.
4261 */
4262
Jiri Slabya0564e12006-12-08 02:38:37 -08004263 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08004265 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
4266 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
4267 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
4269 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Alan Coxb65b5b52006-06-27 02:54:05 -07004271 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 BRDENABLE(portp->brdnr, portp->pagenr);
4273 stl_sc26198setreg(portp, IMR, 0);
4274 stl_sc26198updatereg(portp, MR0, mr0);
4275 stl_sc26198updatereg(portp, MR1, mr1);
4276 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
4277 stl_sc26198updatereg(portp, MR2, mr2);
4278 stl_sc26198updatereg(portp, IOPIOR,
4279 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
4280
4281 if (baudrate > 0) {
4282 stl_sc26198setreg(portp, TXCSR, clk);
4283 stl_sc26198setreg(portp, RXCSR, clk);
4284 }
4285
4286 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
4287 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
4288
4289 ipr = stl_sc26198getreg(portp, IPR);
4290 if (ipr & IPR_DCD)
4291 portp->sigs &= ~TIOCM_CD;
4292 else
4293 portp->sigs |= TIOCM_CD;
4294
4295 portp->imr = (portp->imr & ~imroff) | imron;
4296 stl_sc26198setreg(portp, IMR, portp->imr);
4297 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004298 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299}
4300
4301/*****************************************************************************/
4302
4303/*
4304 * Set the state of the DTR and RTS signals.
4305 */
4306
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004307static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308{
4309 unsigned char iopioron, iopioroff;
4310 unsigned long flags;
4311
Jiri Slabya0564e12006-12-08 02:38:37 -08004312 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4313 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
4315 iopioron = 0;
4316 iopioroff = 0;
4317 if (dtr == 0)
4318 iopioroff |= IPR_DTR;
4319 else if (dtr > 0)
4320 iopioron |= IPR_DTR;
4321 if (rts == 0)
4322 iopioroff |= IPR_RTS;
4323 else if (rts > 0)
4324 iopioron |= IPR_RTS;
4325
Alan Coxb65b5b52006-06-27 02:54:05 -07004326 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 BRDENABLE(portp->brdnr, portp->pagenr);
4328 stl_sc26198setreg(portp, IOPIOR,
4329 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4330 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004331 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332}
4333
4334/*****************************************************************************/
4335
4336/*
4337 * Return the state of the signals.
4338 */
4339
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004340static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341{
4342 unsigned char ipr;
4343 unsigned long flags;
4344 int sigs;
4345
Jiri Slabya0564e12006-12-08 02:38:37 -08004346 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Alan Coxb65b5b52006-06-27 02:54:05 -07004348 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 BRDENABLE(portp->brdnr, portp->pagenr);
4350 ipr = stl_sc26198getreg(portp, IPR);
4351 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004352 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353
4354 sigs = 0;
4355 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4356 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4357 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4358 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4359 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004360 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361}
4362
4363/*****************************************************************************/
4364
4365/*
4366 * Enable/Disable the Transmitter and/or Receiver.
4367 */
4368
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004369static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370{
4371 unsigned char ccr;
4372 unsigned long flags;
4373
Jiri Slabya0564e12006-12-08 02:38:37 -08004374 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
4376 ccr = portp->crenable;
4377 if (tx == 0)
4378 ccr &= ~CR_TXENABLE;
4379 else if (tx > 0)
4380 ccr |= CR_TXENABLE;
4381 if (rx == 0)
4382 ccr &= ~CR_RXENABLE;
4383 else if (rx > 0)
4384 ccr |= CR_RXENABLE;
4385
Alan Coxb65b5b52006-06-27 02:54:05 -07004386 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387 BRDENABLE(portp->brdnr, portp->pagenr);
4388 stl_sc26198setreg(portp, SCCR, ccr);
4389 BRDDISABLE(portp->brdnr);
4390 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004391 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392}
4393
4394/*****************************************************************************/
4395
4396/*
4397 * Start/stop the Transmitter and/or Receiver.
4398 */
4399
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004400static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401{
4402 unsigned char imr;
4403 unsigned long flags;
4404
Jiri Slabya0564e12006-12-08 02:38:37 -08004405 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406
4407 imr = portp->imr;
4408 if (tx == 0)
4409 imr &= ~IR_TXRDY;
4410 else if (tx == 1)
4411 imr |= IR_TXRDY;
4412 if (rx == 0)
4413 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4414 else if (rx > 0)
4415 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4416
Alan Coxb65b5b52006-06-27 02:54:05 -07004417 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 BRDENABLE(portp->brdnr, portp->pagenr);
4419 stl_sc26198setreg(portp, IMR, imr);
4420 BRDDISABLE(portp->brdnr);
4421 portp->imr = imr;
4422 if (tx > 0)
4423 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004424 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425}
4426
4427/*****************************************************************************/
4428
4429/*
4430 * Disable all interrupts from this port.
4431 */
4432
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004433static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434{
4435 unsigned long flags;
4436
Jiri Slabya0564e12006-12-08 02:38:37 -08004437 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Alan Coxb65b5b52006-06-27 02:54:05 -07004439 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 BRDENABLE(portp->brdnr, portp->pagenr);
4441 portp->imr = 0;
4442 stl_sc26198setreg(portp, IMR, 0);
4443 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004444 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445}
4446
4447/*****************************************************************************/
4448
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004449static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450{
4451 unsigned long flags;
4452
Jiri Slabya0564e12006-12-08 02:38:37 -08004453 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454
Alan Coxb65b5b52006-06-27 02:54:05 -07004455 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 BRDENABLE(portp->brdnr, portp->pagenr);
4457 if (len == 1) {
4458 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4459 portp->stats.txbreaks++;
4460 } else {
4461 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
4462 }
4463 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004464 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465}
4466
4467/*****************************************************************************/
4468
4469/*
4470 * Take flow control actions...
4471 */
4472
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004473static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 struct tty_struct *tty;
4476 unsigned long flags;
4477 unsigned char mr0;
4478
Jiri Slabya0564e12006-12-08 02:38:37 -08004479 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Jiri Slaby615e4a72006-12-08 02:38:38 -08004481 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482 return;
4483 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004484 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 return;
4486
Alan Coxb65b5b52006-06-27 02:54:05 -07004487 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 BRDENABLE(portp->brdnr, portp->pagenr);
4489
4490 if (state) {
4491 if (tty->termios->c_iflag & IXOFF) {
4492 mr0 = stl_sc26198getreg(portp, MR0);
4493 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4494 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4495 mr0 |= MR0_SWFRX;
4496 portp->stats.rxxon++;
4497 stl_sc26198wait(portp);
4498 stl_sc26198setreg(portp, MR0, mr0);
4499 }
4500/*
4501 * Question: should we return RTS to what it was before? It may
4502 * have been set by an ioctl... Suppose not, since if you have
4503 * hardware flow control set then it is pretty silly to go and
4504 * set the RTS line by hand.
4505 */
4506 if (tty->termios->c_cflag & CRTSCTS) {
4507 stl_sc26198setreg(portp, MR1,
4508 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4509 stl_sc26198setreg(portp, IOPIOR,
4510 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4511 portp->stats.rxrtson++;
4512 }
4513 } else {
4514 if (tty->termios->c_iflag & IXOFF) {
4515 mr0 = stl_sc26198getreg(portp, MR0);
4516 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4517 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4518 mr0 &= ~MR0_SWFRX;
4519 portp->stats.rxxoff++;
4520 stl_sc26198wait(portp);
4521 stl_sc26198setreg(portp, MR0, mr0);
4522 }
4523 if (tty->termios->c_cflag & CRTSCTS) {
4524 stl_sc26198setreg(portp, MR1,
4525 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4526 stl_sc26198setreg(portp, IOPIOR,
4527 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4528 portp->stats.rxrtsoff++;
4529 }
4530 }
4531
4532 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004533 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004534}
4535
4536/*****************************************************************************/
4537
4538/*
4539 * Send a flow control character.
4540 */
4541
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004542static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543{
4544 struct tty_struct *tty;
4545 unsigned long flags;
4546 unsigned char mr0;
4547
Jiri Slabya0564e12006-12-08 02:38:37 -08004548 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
Jiri Slaby615e4a72006-12-08 02:38:38 -08004550 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551 return;
4552 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004553 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 return;
4555
Alan Coxb65b5b52006-06-27 02:54:05 -07004556 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557 BRDENABLE(portp->brdnr, portp->pagenr);
4558 if (state) {
4559 mr0 = stl_sc26198getreg(portp, MR0);
4560 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4561 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4562 mr0 |= MR0_SWFRX;
4563 portp->stats.rxxon++;
4564 stl_sc26198wait(portp);
4565 stl_sc26198setreg(portp, MR0, mr0);
4566 } else {
4567 mr0 = stl_sc26198getreg(portp, MR0);
4568 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4569 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4570 mr0 &= ~MR0_SWFRX;
4571 portp->stats.rxxoff++;
4572 stl_sc26198wait(portp);
4573 stl_sc26198setreg(portp, MR0, mr0);
4574 }
4575 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004576 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577}
4578
4579/*****************************************************************************/
4580
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004581static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582{
4583 unsigned long flags;
4584
Jiri Slabya0564e12006-12-08 02:38:37 -08004585 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586
Jiri Slaby615e4a72006-12-08 02:38:38 -08004587 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 return;
4589
Alan Coxb65b5b52006-06-27 02:54:05 -07004590 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 BRDENABLE(portp->brdnr, portp->pagenr);
4592 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4593 stl_sc26198setreg(portp, SCCR, portp->crenable);
4594 BRDDISABLE(portp->brdnr);
4595 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004596 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004597}
4598
4599/*****************************************************************************/
4600
4601/*
4602 * Return the current state of data flow on this port. This is only
4603 * really interresting when determining if data has fully completed
4604 * transmission or not... The sc26198 interrupt scheme cannot
4605 * determine when all data has actually drained, so we need to
4606 * check the port statusy register to be sure.
4607 */
4608
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004609static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610{
4611 unsigned long flags;
4612 unsigned char sr;
4613
Jiri Slabya0564e12006-12-08 02:38:37 -08004614 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615
Jiri Slaby615e4a72006-12-08 02:38:38 -08004616 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004617 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004619 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004620
Alan Coxb65b5b52006-06-27 02:54:05 -07004621 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 BRDENABLE(portp->brdnr, portp->pagenr);
4623 sr = stl_sc26198getreg(portp, SR);
4624 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004625 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626
Jesper Juhl014c2542006-01-15 02:37:08 +01004627 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628}
4629
4630/*****************************************************************************/
4631
4632/*
4633 * Delay for a small amount of time, to give the sc26198 a chance
4634 * to process a command...
4635 */
4636
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004637static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004638{
4639 int i;
4640
Jiri Slabya0564e12006-12-08 02:38:37 -08004641 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
Jiri Slaby615e4a72006-12-08 02:38:38 -08004643 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644 return;
4645
4646 for (i = 0; (i < 20); i++)
4647 stl_sc26198getglobreg(portp, TSTR);
4648}
4649
4650/*****************************************************************************/
4651
4652/*
4653 * If we are TX flow controlled and in IXANY mode then we may
4654 * need to unflow control here. We gotta do this because of the
4655 * automatic flow control modes of the sc26198.
4656 */
4657
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004658static inline void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659{
4660 unsigned char mr0;
4661
4662 mr0 = stl_sc26198getreg(portp, MR0);
4663 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4664 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4665 stl_sc26198wait(portp);
4666 stl_sc26198setreg(portp, MR0, mr0);
4667 clear_bit(ASYI_TXFLOWED, &portp->istate);
4668}
4669
4670/*****************************************************************************/
4671
4672/*
4673 * Interrupt service routine for sc26198 panels.
4674 */
4675
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004676static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004678 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679 unsigned int iack;
4680
Alan Coxb65b5b52006-06-27 02:54:05 -07004681 spin_lock(&brd_lock);
4682
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683/*
4684 * Work around bug in sc26198 chip... Cannot have A6 address
4685 * line of UART high, else iack will be returned as 0.
4686 */
4687 outb(0, (iobase + 1));
4688
4689 iack = inb(iobase + XP_IACK);
4690 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4691
4692 if (iack & IVR_RXDATA)
4693 stl_sc26198rxisr(portp, iack);
4694 else if (iack & IVR_TXDATA)
4695 stl_sc26198txisr(portp);
4696 else
4697 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004698
4699 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700}
4701
4702/*****************************************************************************/
4703
4704/*
4705 * Transmit interrupt handler. This has gotta be fast! Handling TX
4706 * chars is pretty simple, stuff as many as possible from the TX buffer
4707 * into the sc26198 FIFO.
4708 * In practice it is possible that interrupts are enabled but that the
4709 * port has been hung up. Need to handle not having any TX buffer here,
4710 * this is done by using the side effect that head and tail will also
4711 * be NULL if the buffer has been freed.
4712 */
4713
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004714static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715{
4716 unsigned int ioaddr;
4717 unsigned char mr0;
4718 int len, stlen;
4719 char *head, *tail;
4720
Jiri Slabya0564e12006-12-08 02:38:37 -08004721 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004722
4723 ioaddr = portp->ioaddr;
4724 head = portp->tx.head;
4725 tail = portp->tx.tail;
4726 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4727 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4728 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4729 set_bit(ASYI_TXLOW, &portp->istate);
4730 schedule_work(&portp->tqueue);
4731 }
4732
4733 if (len == 0) {
4734 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4735 mr0 = inb(ioaddr + XP_DATA);
4736 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4737 portp->imr &= ~IR_TXRDY;
4738 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4739 outb(portp->imr, (ioaddr + XP_DATA));
4740 clear_bit(ASYI_TXBUSY, &portp->istate);
4741 } else {
4742 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4743 outb(mr0, (ioaddr + XP_DATA));
4744 }
4745 } else {
4746 len = MIN(len, SC26198_TXFIFOSIZE);
4747 portp->stats.txtotal += len;
4748 stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
4749 outb(GTXFIFO, (ioaddr + XP_ADDR));
4750 outsb((ioaddr + XP_DATA), tail, stlen);
4751 len -= stlen;
4752 tail += stlen;
4753 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4754 tail = portp->tx.buf;
4755 if (len > 0) {
4756 outsb((ioaddr + XP_DATA), tail, len);
4757 tail += len;
4758 }
4759 portp->tx.tail = tail;
4760 }
4761}
4762
4763/*****************************************************************************/
4764
4765/*
4766 * Receive character interrupt handler. Determine if we have good chars
4767 * or bad chars and then process appropriately. Good chars are easy
4768 * just shove the lot into the RX buffer and set all status byte to 0.
4769 * If a bad RX char then process as required. This routine needs to be
4770 * fast! In practice it is possible that we get an interrupt on a port
4771 * that is closed. This can happen on hangups - since they completely
4772 * shutdown a port not in user context. Need to handle this case.
4773 */
4774
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004775static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776{
4777 struct tty_struct *tty;
4778 unsigned int len, buflen, ioaddr;
4779
Jiri Slabya0564e12006-12-08 02:38:37 -08004780 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781
4782 tty = portp->tty;
4783 ioaddr = portp->ioaddr;
4784 outb(GIBCR, (ioaddr + XP_ADDR));
4785 len = inb(ioaddr + XP_DATA) + 1;
4786
4787 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004788 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789 len = MIN(len, sizeof(stl_unwanted));
4790 outb(GRXFIFO, (ioaddr + XP_ADDR));
4791 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4792 portp->stats.rxlost += len;
4793 portp->stats.rxtotal += len;
4794 } else {
4795 len = MIN(len, buflen);
4796 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004797 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004799 tty_prepare_flip_string(tty, &ptr, len);
4800 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801 tty_schedule_flip(tty);
4802 portp->stats.rxtotal += len;
4803 }
4804 }
4805 } else {
4806 stl_sc26198rxbadchars(portp);
4807 }
4808
4809/*
4810 * If we are TX flow controlled and in IXANY mode then we may need
4811 * to unflow control here. We gotta do this because of the automatic
4812 * flow control modes of the sc26198.
4813 */
4814 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004815 if ((tty != NULL) &&
4816 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817 (tty->termios->c_iflag & IXANY)) {
4818 stl_sc26198txunflow(portp, tty);
4819 }
4820 }
4821}
4822
4823/*****************************************************************************/
4824
4825/*
4826 * Process an RX bad character.
4827 */
4828
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004829static inline void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830{
4831 struct tty_struct *tty;
4832 unsigned int ioaddr;
4833
4834 tty = portp->tty;
4835 ioaddr = portp->ioaddr;
4836
4837 if (status & SR_RXPARITY)
4838 portp->stats.rxparity++;
4839 if (status & SR_RXFRAMING)
4840 portp->stats.rxframing++;
4841 if (status & SR_RXOVERRUN)
4842 portp->stats.rxoverrun++;
4843 if (status & SR_RXBREAK)
4844 portp->stats.rxbreaks++;
4845
Jiri Slaby615e4a72006-12-08 02:38:38 -08004846 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 ((portp->rxignoremsk & status) == 0)) {
4848 if (portp->rxmarkmsk & status) {
4849 if (status & SR_RXBREAK) {
4850 status = TTY_BREAK;
4851 if (portp->flags & ASYNC_SAK) {
4852 do_SAK(tty);
4853 BRDENABLE(portp->brdnr, portp->pagenr);
4854 }
4855 } else if (status & SR_RXPARITY) {
4856 status = TTY_PARITY;
4857 } else if (status & SR_RXFRAMING) {
4858 status = TTY_FRAME;
4859 } else if(status & SR_RXOVERRUN) {
4860 status = TTY_OVERRUN;
4861 } else {
4862 status = 0;
4863 }
4864 } else {
4865 status = 0;
4866 }
4867
Alan Cox33f0f882006-01-09 20:54:13 -08004868 tty_insert_flip_char(tty, ch, status);
4869 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870
4871 if (status == 0)
4872 portp->stats.rxtotal++;
4873 }
4874}
4875
4876/*****************************************************************************/
4877
4878/*
4879 * Process all characters in the RX FIFO of the UART. Check all char
4880 * status bytes as well, and process as required. We need to check
4881 * all bytes in the FIFO, in case some more enter the FIFO while we
4882 * are here. To get the exact character error type we need to switch
4883 * into CHAR error mode (that is why we need to make sure we empty
4884 * the FIFO).
4885 */
4886
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004887static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888{
4889 unsigned char status, mr1;
4890 char ch;
4891
4892/*
4893 * To get the precise error type for each character we must switch
4894 * back into CHAR error mode.
4895 */
4896 mr1 = stl_sc26198getreg(portp, MR1);
4897 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4898
4899 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4900 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4901 ch = stl_sc26198getreg(portp, RXFIFO);
4902 stl_sc26198rxbadch(portp, status, ch);
4903 }
4904
4905/*
4906 * To get correct interrupt class we must switch back into BLOCK
4907 * error mode.
4908 */
4909 stl_sc26198setreg(portp, MR1, mr1);
4910}
4911
4912/*****************************************************************************/
4913
4914/*
4915 * Other interrupt handler. This includes modem signals, flow
4916 * control actions, etc. Most stuff is left to off-level interrupt
4917 * processing time.
4918 */
4919
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004920static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921{
4922 unsigned char cir, ipr, xisr;
4923
Jiri Slabya0564e12006-12-08 02:38:37 -08004924 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925
4926 cir = stl_sc26198getglobreg(portp, CIR);
4927
4928 switch (cir & CIR_SUBTYPEMASK) {
4929 case CIR_SUBCOS:
4930 ipr = stl_sc26198getreg(portp, IPR);
4931 if (ipr & IPR_DCDCHANGE) {
4932 set_bit(ASYI_DCDCHANGE, &portp->istate);
4933 schedule_work(&portp->tqueue);
4934 portp->stats.modem++;
4935 }
4936 break;
4937 case CIR_SUBXONXOFF:
4938 xisr = stl_sc26198getreg(portp, XISR);
4939 if (xisr & XISR_RXXONGOT) {
4940 set_bit(ASYI_TXFLOWED, &portp->istate);
4941 portp->stats.txxoff++;
4942 }
4943 if (xisr & XISR_RXXOFFGOT) {
4944 clear_bit(ASYI_TXFLOWED, &portp->istate);
4945 portp->stats.txxon++;
4946 }
4947 break;
4948 case CIR_SUBBREAK:
4949 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4950 stl_sc26198rxbadchars(portp);
4951 break;
4952 default:
4953 break;
4954 }
4955}
4956
4957/*****************************************************************************/