blob: 983244ab1362ce1252a38c0f40b04df967bb26b7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * stallion.c -- stallion multiport serial driver.
5 *
6 * Copyright (C) 1996-1999 Stallion Technologies
7 * Copyright (C) 1994-1996 Greg Ungerer.
8 *
9 * This code is loosely based on the Linux serial driver, written by
10 * Linus Torvalds, Theodore T'so and others.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*****************************************************************************/
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
35#include <linux/cd1400.h>
36#include <linux/sc26198.h>
37#include <linux/comstats.h>
38#include <linux/stallion.h>
39#include <linux/ioport.h>
40#include <linux/init.h>
41#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/device.h>
43#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080044#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <asm/io.h>
47#include <asm/uaccess.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51/*****************************************************************************/
52
53/*
54 * Define different board types. Use the standard Stallion "assigned"
55 * board numbers. Boards supported in this driver are abbreviated as
56 * EIO = EasyIO and ECH = EasyConnection 8/32.
57 */
58#define BRD_EASYIO 20
59#define BRD_ECH 21
60#define BRD_ECHMC 22
61#define BRD_ECHPCI 26
62#define BRD_ECH64PCI 27
63#define BRD_EASYIOPCI 28
64
Jiri Slaby843b5682006-12-08 02:39:12 -080065struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080066 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int ioaddr1;
68 int ioaddr2;
69 unsigned long memaddr;
70 int irq;
71 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072};
73
Jiri Slaby843b5682006-12-08 02:39:12 -080074static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76/*****************************************************************************/
77
78/*
79 * Define some important driver characteristics. Device major numbers
80 * allocated as per Linux Device Registry.
81 */
82#ifndef STL_SIOMEMMAJOR
83#define STL_SIOMEMMAJOR 28
84#endif
85#ifndef STL_SERIALMAJOR
86#define STL_SERIALMAJOR 24
87#endif
88#ifndef STL_CALLOUTMAJOR
89#define STL_CALLOUTMAJOR 25
90#endif
91
92/*
93 * Set the TX buffer size. Bigger is better, but we don't want
94 * to chew too much memory with buffers!
95 */
96#define STL_TXBUFLOW 512
97#define STL_TXBUFSIZE 4096
98
99/*****************************************************************************/
100
101/*
102 * Define our local driver identity first. Set up stuff to deal with
103 * all the local structures required by a serial tty driver.
104 */
105static char *stl_drvtitle = "Stallion Multiport Serial Driver";
106static char *stl_drvname = "stallion";
107static char *stl_drvversion = "5.6.0";
108
109static struct tty_driver *stl_serial;
110
111/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * Define a local default termios struct. All ports will be created
113 * with this termios initially. Basically all it defines is a raw port
114 * at 9600, 8 data bits, 1 stop bit.
115 */
Alan Cox606d0992006-12-08 02:38:45 -0800116static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
118 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800119 .c_ispeed = 9600,
120 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 * Define global place to put buffer overflow characters.
125 */
126static char stl_unwanted[SC26198_RXFIFOSIZE];
127
128/*****************************************************************************/
129
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800130static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800131static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/*
134 * Per board state flags. Used with the state field of the board struct.
135 * Not really much here!
136 */
137#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800138#define STL_PROBED 0x2
139
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
141/*
142 * Define the port structure istate flags. These set of flags are
143 * modified at interrupt time - so setting and reseting them needs
144 * to be atomic. Use the bit clear/setting routines for this.
145 */
146#define ASYI_TXBUSY 1
147#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800148#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/*
151 * Define an array of board names as printable strings. Handy for
152 * referencing boards when printing trace and stuff.
153 */
154static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800155 NULL,
156 NULL,
157 NULL,
158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 "EasyIO",
176 "EC8/32-AT",
177 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800178 NULL,
179 NULL,
180 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 "EC8/32-PCI",
182 "EC8/64-PCI",
183 "EasyIO-PCI",
184};
185
186/*****************************************************************************/
187
188/*
189 * Define some string labels for arguments passed from the module
190 * load line. These allow for easy board definitions, and easy
191 * modification of the io, memory and irq resoucres.
192 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800193static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static char *board0[4];
195static char *board1[4];
196static char *board2[4];
197static char *board3[4];
198
199static char **stl_brdsp[] = {
200 (char **) &board0,
201 (char **) &board1,
202 (char **) &board2,
203 (char **) &board3
204};
205
206/*
207 * Define a set of common board names, and types. This is used to
208 * parse any module arguments.
209 */
210
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800211static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 char *name;
213 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800214} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 { "easyio", BRD_EASYIO },
216 { "eio", BRD_EASYIO },
217 { "20", BRD_EASYIO },
218 { "ec8/32", BRD_ECH },
219 { "ec8/32-at", BRD_ECH },
220 { "ec8/32-isa", BRD_ECH },
221 { "ech", BRD_ECH },
222 { "echat", BRD_ECH },
223 { "21", BRD_ECH },
224 { "ec8/32-mc", BRD_ECHMC },
225 { "ec8/32-mca", BRD_ECHMC },
226 { "echmc", BRD_ECHMC },
227 { "echmca", BRD_ECHMC },
228 { "22", BRD_ECHMC },
229 { "ec8/32-pc", BRD_ECHPCI },
230 { "ec8/32-pci", BRD_ECHPCI },
231 { "26", BRD_ECHPCI },
232 { "ec8/64-pc", BRD_ECH64PCI },
233 { "ec8/64-pci", BRD_ECH64PCI },
234 { "ech-pci", BRD_ECH64PCI },
235 { "echpci", BRD_ECH64PCI },
236 { "echpc", BRD_ECH64PCI },
237 { "27", BRD_ECH64PCI },
238 { "easyio-pc", BRD_EASYIOPCI },
239 { "easyio-pci", BRD_EASYIOPCI },
240 { "eio-pci", BRD_EASYIOPCI },
241 { "eiopci", BRD_EASYIOPCI },
242 { "28", BRD_EASYIOPCI },
243};
244
245/*
246 * Define the module agruments.
247 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249module_param_array(board0, charp, &stl_nargs, 0);
250MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
251module_param_array(board1, charp, &stl_nargs, 0);
252MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
253module_param_array(board2, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board3, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
257
258/*****************************************************************************/
259
260/*
261 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
262 * to the directly accessible io ports of these boards (not the uarts -
263 * they are in cd1400.h and sc26198.h).
264 */
265#define EIO_8PORTRS 0x04
266#define EIO_4PORTRS 0x05
267#define EIO_8PORTDI 0x00
268#define EIO_8PORTM 0x06
269#define EIO_MK3 0x03
270#define EIO_IDBITMASK 0x07
271
272#define EIO_BRDMASK 0xf0
273#define ID_BRD4 0x10
274#define ID_BRD8 0x20
275#define ID_BRD16 0x30
276
277#define EIO_INTRPEND 0x08
278#define EIO_INTEDGE 0x00
279#define EIO_INTLEVEL 0x08
280#define EIO_0WS 0x10
281
282#define ECH_ID 0xa0
283#define ECH_IDBITMASK 0xe0
284#define ECH_BRDENABLE 0x08
285#define ECH_BRDDISABLE 0x00
286#define ECH_INTENABLE 0x01
287#define ECH_INTDISABLE 0x00
288#define ECH_INTLEVEL 0x02
289#define ECH_INTEDGE 0x00
290#define ECH_INTRPEND 0x01
291#define ECH_BRDRESET 0x01
292
293#define ECHMC_INTENABLE 0x01
294#define ECHMC_BRDRESET 0x02
295
296#define ECH_PNLSTATUS 2
297#define ECH_PNL16PORT 0x20
298#define ECH_PNLIDMASK 0x07
299#define ECH_PNLXPID 0x40
300#define ECH_PNLINTRPEND 0x80
301
302#define ECH_ADDR2MASK 0x1e0
303
304/*
305 * Define the vector mapping bits for the programmable interrupt board
306 * hardware. These bits encode the interrupt for the board to use - it
307 * is software selectable (except the EIO-8M).
308 */
309static unsigned char stl_vecmap[] = {
310 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
311 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
312};
313
314/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700315 * Lock ordering is that you may not take stallion_lock holding
316 * brd_lock.
317 */
318
319static spinlock_t brd_lock; /* Guard the board mapping */
320static spinlock_t stallion_lock; /* Guard the tty driver */
321
322/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 * Set up enable and disable macros for the ECH boards. They require
324 * the secondary io address space to be activated and deactivated.
325 * This way all ECH boards can share their secondary io region.
326 * If this is an ECH-PCI board then also need to set the page pointer
327 * to point to the correct page.
328 */
329#define BRDENABLE(brdnr,pagenr) \
330 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
331 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
332 stl_brds[(brdnr)]->ioctrl); \
333 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
334 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
335
336#define BRDDISABLE(brdnr) \
337 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
338 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
339 stl_brds[(brdnr)]->ioctrl);
340
341#define STL_CD1400MAXBAUD 230400
342#define STL_SC26198MAXBAUD 460800
343
344#define STL_BAUDBASE 115200
345#define STL_CLOSEDELAY (5 * HZ / 10)
346
347/*****************************************************************************/
348
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349/*
350 * Define the Stallion PCI vendor and device IDs.
351 */
352#ifndef PCI_VENDOR_ID_STALLION
353#define PCI_VENDOR_ID_STALLION 0x124d
354#endif
355#ifndef PCI_DEVICE_ID_ECHPCI832
356#define PCI_DEVICE_ID_ECHPCI832 0x0000
357#endif
358#ifndef PCI_DEVICE_ID_ECHPCI864
359#define PCI_DEVICE_ID_ECHPCI864 0x0002
360#endif
361#ifndef PCI_DEVICE_ID_EIOPCI
362#define PCI_DEVICE_ID_EIOPCI 0x0003
363#endif
364
365/*
366 * Define structure to hold all Stallion PCI boards.
367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800369static struct pci_device_id stl_pcibrds[] = {
370 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
371 .driver_data = BRD_ECH64PCI },
372 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
373 .driver_data = BRD_EASYIOPCI },
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
375 .driver_data = BRD_ECHPCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
377 .driver_data = BRD_ECHPCI },
378 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800380MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382/*****************************************************************************/
383
384/*
385 * Define macros to extract a brd/port number from a minor number.
386 */
387#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
388#define MINOR2PORT(min) ((min) & 0x3f)
389
390/*
391 * Define a baud rate table that converts termios baud rate selector
392 * into the actual baud rate value. All baud rate calculations are
393 * based on the actual baud rate required.
394 */
395static unsigned int stl_baudrates[] = {
396 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
397 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
398};
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400/*****************************************************************************/
401
402/*
403 * Declare all those functions in this driver!
404 */
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800407static int stl_brdinit(struct stlbrd *brdp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800408static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
409static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800410static int stl_waitcarrier(struct stlport *portp, struct file *filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412/*
413 * CD1400 uart specific handling functions.
414 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800415static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
416static int stl_cd1400getreg(struct stlport *portp, int regnr);
417static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
419static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800420static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800421static int stl_cd1400getsignals(struct stlport *portp);
422static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
423static void stl_cd1400ccrwait(struct stlport *portp);
424static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
425static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
426static void stl_cd1400disableintrs(struct stlport *portp);
427static void stl_cd1400sendbreak(struct stlport *portp, int len);
428static void stl_cd1400flowctrl(struct stlport *portp, int state);
429static void stl_cd1400sendflow(struct stlport *portp, int state);
430static void stl_cd1400flush(struct stlport *portp);
431static int stl_cd1400datastate(struct stlport *portp);
432static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
433static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
434static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
435static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
436static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800438static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440/*
441 * SC26198 uart specific handling functions.
442 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800443static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
444static int stl_sc26198getreg(struct stlport *portp, int regnr);
445static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
447static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
448static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800449static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800450static int stl_sc26198getsignals(struct stlport *portp);
451static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
452static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
453static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
454static void stl_sc26198disableintrs(struct stlport *portp);
455static void stl_sc26198sendbreak(struct stlport *portp, int len);
456static void stl_sc26198flowctrl(struct stlport *portp, int state);
457static void stl_sc26198sendflow(struct stlport *portp, int state);
458static void stl_sc26198flush(struct stlport *portp);
459static int stl_sc26198datastate(struct stlport *portp);
460static void stl_sc26198wait(struct stlport *portp);
461static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
462static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
463static void stl_sc26198txisr(struct stlport *port);
464static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
465static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
466static void stl_sc26198rxbadchars(struct stlport *portp);
467static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469/*****************************************************************************/
470
471/*
472 * Generic UART support structure.
473 */
474typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800475 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
476 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800477 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800478 int (*getsignals)(struct stlport *portp);
479 void (*setsignals)(struct stlport *portp, int dtr, int rts);
480 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
481 void (*startrxtx)(struct stlport *portp, int rx, int tx);
482 void (*disableintrs)(struct stlport *portp);
483 void (*sendbreak)(struct stlport *portp, int len);
484 void (*flowctrl)(struct stlport *portp, int state);
485 void (*sendflow)(struct stlport *portp, int state);
486 void (*flush)(struct stlport *portp);
487 int (*datastate)(struct stlport *portp);
488 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489} uart_t;
490
491/*
492 * Define some macros to make calling these functions nice and clean.
493 */
494#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
495#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
496#define stl_setport (* ((uart_t *) portp->uartp)->setport)
497#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
498#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
499#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
500#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
501#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
502#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
503#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
504#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
505#define stl_flush (* ((uart_t *) portp->uartp)->flush)
506#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
507
508/*****************************************************************************/
509
510/*
511 * CD1400 UART specific data initialization.
512 */
513static uart_t stl_cd1400uart = {
514 stl_cd1400panelinit,
515 stl_cd1400portinit,
516 stl_cd1400setport,
517 stl_cd1400getsignals,
518 stl_cd1400setsignals,
519 stl_cd1400enablerxtx,
520 stl_cd1400startrxtx,
521 stl_cd1400disableintrs,
522 stl_cd1400sendbreak,
523 stl_cd1400flowctrl,
524 stl_cd1400sendflow,
525 stl_cd1400flush,
526 stl_cd1400datastate,
527 stl_cd1400eiointr
528};
529
530/*
531 * Define the offsets within the register bank of a cd1400 based panel.
532 * These io address offsets are common to the EasyIO board as well.
533 */
534#define EREG_ADDR 0
535#define EREG_DATA 4
536#define EREG_RXACK 5
537#define EREG_TXACK 6
538#define EREG_MDACK 7
539
540#define EREG_BANKSIZE 8
541
542#define CD1400_CLK 25000000
543#define CD1400_CLK8M 20000000
544
545/*
546 * Define the cd1400 baud rate clocks. These are used when calculating
547 * what clock and divisor to use for the required baud rate. Also
548 * define the maximum baud rate allowed, and the default base baud.
549 */
550static int stl_cd1400clkdivs[] = {
551 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
552};
553
554/*****************************************************************************/
555
556/*
557 * SC26198 UART specific data initization.
558 */
559static uart_t stl_sc26198uart = {
560 stl_sc26198panelinit,
561 stl_sc26198portinit,
562 stl_sc26198setport,
563 stl_sc26198getsignals,
564 stl_sc26198setsignals,
565 stl_sc26198enablerxtx,
566 stl_sc26198startrxtx,
567 stl_sc26198disableintrs,
568 stl_sc26198sendbreak,
569 stl_sc26198flowctrl,
570 stl_sc26198sendflow,
571 stl_sc26198flush,
572 stl_sc26198datastate,
573 stl_sc26198intr
574};
575
576/*
577 * Define the offsets within the register bank of a sc26198 based panel.
578 */
579#define XP_DATA 0
580#define XP_ADDR 1
581#define XP_MODID 2
582#define XP_STATUS 2
583#define XP_IACK 3
584
585#define XP_BANKSIZE 4
586
587/*
588 * Define the sc26198 baud rate table. Offsets within the table
589 * represent the actual baud rate selector of sc26198 registers.
590 */
591static unsigned int sc26198_baudtable[] = {
592 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
593 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
594 230400, 460800, 921600
595};
596
Tobias Klauserfe971072006-01-09 20:54:02 -0800597#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599/*****************************************************************************/
600
601/*
602 * Define the driver info for a user level control device. Used mainly
603 * to get at port stats - only not using the port device itself.
604 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700605static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 .owner = THIS_MODULE,
607 .ioctl = stl_memioctl,
608};
609
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800610static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800612static void stl_cd_change(struct stlport *portp)
613{
614 unsigned int oldsigs = portp->sigs;
615
616 if (!portp->tty)
617 return;
618
619 portp->sigs = stl_getsignals(portp);
620
621 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
622 wake_up_interruptible(&portp->open_wait);
623
624 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
625 if (portp->flags & ASYNC_CHECK_CD)
626 tty_hangup(portp->tty);
627}
628
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 * Check for any arguments passed in on the module load command line.
631 */
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633/*****************************************************************************/
634
635/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 * Parse the supplied argument string, into the board conf struct.
637 */
638
Jiri Slaby40e82652006-12-08 02:38:41 -0800639static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
641 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800642 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Jiri Slabya0564e12006-12-08 02:38:37 -0800644 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Jiri Slaby615e4a72006-12-08 02:38:38 -0800646 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slabyc62429d2006-12-08 02:39:14 -0800649 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800650 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Jiri Slabyc62429d2006-12-08 02:39:14 -0800652 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
654 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800655
Tobias Klauserfe971072006-01-09 20:54:02 -0800656 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800658 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660
661 confp->brdtype = stl_brdstr[i].type;
662
663 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800664 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800665 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 i++;
667 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800668 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800669 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 i++;
671 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800672 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800673 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100674 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675}
676
677/*****************************************************************************/
678
679/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 * Allocate a new board structure. Fill out the basic info in it.
681 */
682
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800683static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800685 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800687 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800688 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700689 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800691 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 }
693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100695 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696}
697
698/*****************************************************************************/
699
700static int stl_open(struct tty_struct *tty, struct file *filp)
701{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800702 struct stlport *portp;
703 struct stlbrd *brdp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800704 unsigned int minordev, brdnr, panelnr;
705 int portnr, rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Jiri Slabya0564e12006-12-08 02:38:37 -0800707 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 minordev = tty->index;
710 brdnr = MINOR2BRD(minordev);
711 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100712 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800714 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100715 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800717 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800718 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 break;
720 if (minordev < brdp->panels[panelnr]->nrports) {
721 portnr = minordev;
722 break;
723 }
724 minordev -= brdp->panels[panelnr]->nrports;
725 }
726 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100727 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
729 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800730 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100731 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733/*
734 * On the first open of the device setup the port hardware, and
735 * initialize the per port data structure.
736 */
737 portp->tty = tty;
738 tty->driver_data = portp;
739 portp->refcount++;
740
741 if ((portp->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800742 if (!portp->tx.buf) {
743 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
744 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100745 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 portp->tx.head = portp->tx.buf;
747 portp->tx.tail = portp->tx.buf;
748 }
749 stl_setport(portp, tty->termios);
750 portp->sigs = stl_getsignals(portp);
751 stl_setsignals(portp, 1, 1);
752 stl_enablerxtx(portp, 1, 1);
753 stl_startrxtx(portp, 1, 0);
754 clear_bit(TTY_IO_ERROR, &tty->flags);
755 portp->flags |= ASYNC_INITIALIZED;
756 }
757
758/*
759 * Check if this port is in the middle of closing. If so then wait
760 * until it is closed then return error status, based on flag settings.
761 * The sleep here does not need interrupt protection since the wakeup
762 * for it is done with the same context.
763 */
764 if (portp->flags & ASYNC_CLOSING) {
765 interruptible_sleep_on(&portp->close_wait);
766 if (portp->flags & ASYNC_HUP_NOTIFY)
Jesper Juhl014c2542006-01-15 02:37:08 +0100767 return -EAGAIN;
768 return -ERESTARTSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
770
771/*
772 * Based on type of open being done check if it can overlap with any
773 * previous opens still in effect. If we are a normal serial device
774 * then also we might have to wait for carrier.
775 */
Jiri Slabyc62429d2006-12-08 02:39:14 -0800776 if (!(filp->f_flags & O_NONBLOCK))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 if ((rc = stl_waitcarrier(portp, filp)) != 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100778 return rc;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 portp->flags |= ASYNC_NORMAL_ACTIVE;
781
Jesper Juhl014c2542006-01-15 02:37:08 +0100782 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783}
784
785/*****************************************************************************/
786
787/*
788 * Possibly need to wait for carrier (DCD signal) to come high. Say
789 * maybe because if we are clocal then we don't need to wait...
790 */
791
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800792static int stl_waitcarrier(struct stlport *portp, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
794 unsigned long flags;
795 int rc, doclocal;
796
Jiri Slabya0564e12006-12-08 02:38:37 -0800797 pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
799 rc = 0;
800 doclocal = 0;
801
Alan Coxb65b5b52006-06-27 02:54:05 -0700802 spin_lock_irqsave(&stallion_lock, flags);
803
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 if (portp->tty->termios->c_cflag & CLOCAL)
805 doclocal++;
806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 portp->openwaitcnt++;
808 if (! tty_hung_up_p(filp))
809 portp->refcount--;
810
811 for (;;) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700812 /* Takes brd_lock internally */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 stl_setsignals(portp, 1, 1);
814 if (tty_hung_up_p(filp) ||
815 ((portp->flags & ASYNC_INITIALIZED) == 0)) {
816 if (portp->flags & ASYNC_HUP_NOTIFY)
817 rc = -EBUSY;
818 else
819 rc = -ERESTARTSYS;
820 break;
821 }
822 if (((portp->flags & ASYNC_CLOSING) == 0) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -0800823 (doclocal || (portp->sigs & TIOCM_CD)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 if (signal_pending(current)) {
826 rc = -ERESTARTSYS;
827 break;
828 }
Alan Coxb65b5b52006-06-27 02:54:05 -0700829 /* FIXME */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 interruptible_sleep_on(&portp->open_wait);
831 }
832
833 if (! tty_hung_up_p(filp))
834 portp->refcount++;
835 portp->openwaitcnt--;
Alan Coxb65b5b52006-06-27 02:54:05 -0700836 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Jesper Juhl014c2542006-01-15 02:37:08 +0100838 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839}
840
841/*****************************************************************************/
842
Jiri Slaby96b066b2006-12-08 02:38:42 -0800843static void stl_flushbuffer(struct tty_struct *tty)
844{
845 struct stlport *portp;
846
847 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
848
849 if (tty == NULL)
850 return;
851 portp = tty->driver_data;
852 if (portp == NULL)
853 return;
854
855 stl_flush(portp);
856 tty_wakeup(tty);
857}
858
859/*****************************************************************************/
860
861static void stl_waituntilsent(struct tty_struct *tty, int timeout)
862{
863 struct stlport *portp;
864 unsigned long tend;
865
866 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
867
868 if (tty == NULL)
869 return;
870 portp = tty->driver_data;
871 if (portp == NULL)
872 return;
873
874 if (timeout == 0)
875 timeout = HZ;
876 tend = jiffies + timeout;
877
878 while (stl_datastate(portp)) {
879 if (signal_pending(current))
880 break;
881 msleep_interruptible(20);
882 if (time_after_eq(jiffies, tend))
883 break;
884 }
885}
886
887/*****************************************************************************/
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889static void stl_close(struct tty_struct *tty, struct file *filp)
890{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800891 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 unsigned long flags;
893
Jiri Slabya0564e12006-12-08 02:38:37 -0800894 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800897 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 return;
899
Alan Coxb65b5b52006-06-27 02:54:05 -0700900 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (tty_hung_up_p(filp)) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700902 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return;
904 }
905 if ((tty->count == 1) && (portp->refcount != 1))
906 portp->refcount = 1;
907 if (portp->refcount-- > 1) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700908 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 return;
910 }
911
912 portp->refcount = 0;
913 portp->flags |= ASYNC_CLOSING;
914
915/*
916 * May want to wait for any data to drain before closing. The BUSY
917 * flag keeps track of whether we are still sending or not - it is
918 * very accurate for the cd1400, not quite so for the sc26198.
919 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
920 */
921 tty->closing = 1;
Alan Coxb65b5b52006-06-27 02:54:05 -0700922
923 spin_unlock_irqrestore(&stallion_lock, flags);
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
926 tty_wait_until_sent(tty, portp->closing_wait);
927 stl_waituntilsent(tty, (HZ / 2));
928
Alan Coxb65b5b52006-06-27 02:54:05 -0700929
930 spin_lock_irqsave(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 portp->flags &= ~ASYNC_INITIALIZED;
Alan Coxb65b5b52006-06-27 02:54:05 -0700932 spin_unlock_irqrestore(&stallion_lock, flags);
933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 stl_disableintrs(portp);
935 if (tty->termios->c_cflag & HUPCL)
936 stl_setsignals(portp, 0, 0);
937 stl_enablerxtx(portp, 0, 0);
938 stl_flushbuffer(tty);
939 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800940 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800942 portp->tx.buf = NULL;
943 portp->tx.head = NULL;
944 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 }
946 set_bit(TTY_IO_ERROR, &tty->flags);
947 tty_ldisc_flush(tty);
948
949 tty->closing = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800950 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
952 if (portp->openwaitcnt) {
953 if (portp->close_delay)
954 msleep_interruptible(jiffies_to_msecs(portp->close_delay));
955 wake_up_interruptible(&portp->open_wait);
956 }
957
958 portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
959 wake_up_interruptible(&portp->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960}
961
962/*****************************************************************************/
963
964/*
965 * Write routine. Take data and stuff it in to the TX ring queue.
966 * If transmit interrupts are not running then start them.
967 */
968
969static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
970{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800971 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 unsigned int len, stlen;
973 unsigned char *chbuf;
974 char *head, *tail;
975
Jiri Slabya0564e12006-12-08 02:38:37 -0800976 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800979 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100980 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800981 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100982 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984/*
985 * If copying direct from user space we must cater for page faults,
986 * causing us to "sleep" here for a while. To handle this copy in all
987 * the data we need now, into a local buffer. Then when we got it all
988 * copy it into the TX buffer.
989 */
990 chbuf = (unsigned char *) buf;
991
992 head = portp->tx.head;
993 tail = portp->tx.tail;
994 if (head >= tail) {
995 len = STL_TXBUFSIZE - (head - tail) - 1;
996 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
997 } else {
998 len = tail - head - 1;
999 stlen = len;
1000 }
1001
Jiri Slaby843b5682006-12-08 02:39:12 -08001002 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 count = 0;
1004 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -08001005 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 memcpy(head, chbuf, stlen);
1007 len -= stlen;
1008 chbuf += stlen;
1009 count += stlen;
1010 head += stlen;
1011 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
1012 head = portp->tx.buf;
1013 stlen = tail - head;
1014 }
1015 }
1016 portp->tx.head = head;
1017
1018 clear_bit(ASYI_TXLOW, &portp->istate);
1019 stl_startrxtx(portp, -1, 1);
1020
Jesper Juhl014c2542006-01-15 02:37:08 +01001021 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022}
1023
1024/*****************************************************************************/
1025
1026static void stl_putchar(struct tty_struct *tty, unsigned char ch)
1027{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001028 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 unsigned int len;
1030 char *head, *tail;
1031
Jiri Slabya0564e12006-12-08 02:38:37 -08001032 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
Jiri Slaby615e4a72006-12-08 02:38:38 -08001034 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return;
1036 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001037 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001039 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 return;
1041
1042 head = portp->tx.head;
1043 tail = portp->tx.tail;
1044
1045 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
1046 len--;
1047
1048 if (len > 0) {
1049 *head++ = ch;
1050 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
1051 head = portp->tx.buf;
1052 }
1053 portp->tx.head = head;
1054}
1055
1056/*****************************************************************************/
1057
1058/*
1059 * If there are any characters in the buffer then make sure that TX
1060 * interrupts are on and get'em out. Normally used after the putchar
1061 * routine has been called.
1062 */
1063
1064static void stl_flushchars(struct tty_struct *tty)
1065{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001066 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Jiri Slabya0564e12006-12-08 02:38:37 -08001068 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Jiri Slaby615e4a72006-12-08 02:38:38 -08001070 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 return;
1072 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001075 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 return;
1077
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 stl_startrxtx(portp, -1, 1);
1079}
1080
1081/*****************************************************************************/
1082
1083static int stl_writeroom(struct tty_struct *tty)
1084{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001085 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 char *head, *tail;
1087
Jiri Slabya0564e12006-12-08 02:38:37 -08001088 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Jiri Slaby615e4a72006-12-08 02:38:38 -08001090 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001091 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001093 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001094 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001095 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001096 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098 head = portp->tx.head;
1099 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001100 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101}
1102
1103/*****************************************************************************/
1104
1105/*
1106 * Return number of chars in the TX buffer. Normally we would just
1107 * calculate the number of chars in the buffer and return that, but if
1108 * the buffer is empty and TX interrupts are still on then we return
1109 * that the buffer still has 1 char in it. This way whoever called us
1110 * will not think that ALL chars have drained - since the UART still
1111 * must have some chars in it (we are busy after all).
1112 */
1113
1114static int stl_charsinbuffer(struct tty_struct *tty)
1115{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001116 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 unsigned int size;
1118 char *head, *tail;
1119
Jiri Slabya0564e12006-12-08 02:38:37 -08001120 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Jiri Slaby615e4a72006-12-08 02:38:38 -08001122 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001123 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001125 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001126 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001127 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001128 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
1130 head = portp->tx.head;
1131 tail = portp->tx.tail;
1132 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1133 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1134 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001135 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136}
1137
1138/*****************************************************************************/
1139
1140/*
1141 * Generate the serial struct info.
1142 */
1143
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001144static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145{
1146 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001147 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Jiri Slabya0564e12006-12-08 02:38:37 -08001149 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150
1151 memset(&sio, 0, sizeof(struct serial_struct));
1152 sio.line = portp->portnr;
1153 sio.port = portp->ioaddr;
1154 sio.flags = portp->flags;
1155 sio.baud_base = portp->baud_base;
1156 sio.close_delay = portp->close_delay;
1157 sio.closing_wait = portp->closing_wait;
1158 sio.custom_divisor = portp->custom_divisor;
1159 sio.hub6 = 0;
1160 if (portp->uartp == &stl_cd1400uart) {
1161 sio.type = PORT_CIRRUS;
1162 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1163 } else {
1164 sio.type = PORT_UNKNOWN;
1165 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1166 }
1167
1168 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001169 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 sio.irq = brdp->irq;
1171
1172 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1173}
1174
1175/*****************************************************************************/
1176
1177/*
1178 * Set port according to the serial struct info.
1179 * At this point we do not do any auto-configure stuff, so we will
1180 * just quietly ignore any requests to change irq, etc.
1181 */
1182
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001183static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184{
1185 struct serial_struct sio;
1186
Jiri Slabya0564e12006-12-08 02:38:37 -08001187 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
1189 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1190 return -EFAULT;
1191 if (!capable(CAP_SYS_ADMIN)) {
1192 if ((sio.baud_base != portp->baud_base) ||
1193 (sio.close_delay != portp->close_delay) ||
1194 ((sio.flags & ~ASYNC_USR_MASK) !=
1195 (portp->flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001196 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
1198
1199 portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
1200 (sio.flags & ASYNC_USR_MASK);
1201 portp->baud_base = sio.baud_base;
1202 portp->close_delay = sio.close_delay;
1203 portp->closing_wait = sio.closing_wait;
1204 portp->custom_divisor = sio.custom_divisor;
1205 stl_setport(portp, portp->tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001206 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207}
1208
1209/*****************************************************************************/
1210
1211static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1212{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001213 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Jiri Slaby615e4a72006-12-08 02:38:38 -08001215 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001216 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001218 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001219 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001221 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
1223 return stl_getsignals(portp);
1224}
1225
1226static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1227 unsigned int set, unsigned int clear)
1228{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001229 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 int rts = -1, dtr = -1;
1231
Jiri Slaby615e4a72006-12-08 02:38:38 -08001232 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001233 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001235 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001236 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001238 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 if (set & TIOCM_RTS)
1241 rts = 1;
1242 if (set & TIOCM_DTR)
1243 dtr = 1;
1244 if (clear & TIOCM_RTS)
1245 rts = 0;
1246 if (clear & TIOCM_DTR)
1247 dtr = 0;
1248
1249 stl_setsignals(portp, dtr, rts);
1250 return 0;
1251}
1252
1253static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1254{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001255 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 unsigned int ival;
1257 int rc;
1258 void __user *argp = (void __user *)arg;
1259
Jiri Slabya0564e12006-12-08 02:38:37 -08001260 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1261 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Jiri Slaby615e4a72006-12-08 02:38:38 -08001263 if (tty == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001264 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001266 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001267 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
1269 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001270 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001272 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 rc = 0;
1275
Alan Coxf433c652008-04-30 00:53:23 -07001276 lock_kernel();
1277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 case TIOCGSERIAL:
1280 rc = stl_getserial(portp, argp);
1281 break;
1282 case TIOCSSERIAL:
1283 rc = stl_setserial(portp, argp);
1284 break;
1285 case COM_GETPORTSTATS:
1286 rc = stl_getportstats(portp, argp);
1287 break;
1288 case COM_CLRPORTSTATS:
1289 rc = stl_clrportstats(portp, argp);
1290 break;
1291 case TIOCSERCONFIG:
1292 case TIOCSERGWILD:
1293 case TIOCSERSWILD:
1294 case TIOCSERGETLSR:
1295 case TIOCSERGSTRUCT:
1296 case TIOCSERGETMULTI:
1297 case TIOCSERSETMULTI:
1298 default:
1299 rc = -ENOIOCTLCMD;
1300 break;
1301 }
Alan Coxf433c652008-04-30 00:53:23 -07001302 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001303 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304}
1305
1306/*****************************************************************************/
1307
Jiri Slaby96b066b2006-12-08 02:38:42 -08001308/*
1309 * Start the transmitter again. Just turn TX interrupts back on.
1310 */
1311
1312static void stl_start(struct tty_struct *tty)
1313{
1314 struct stlport *portp;
1315
1316 pr_debug("stl_start(tty=%p)\n", tty);
1317
1318 if (tty == NULL)
1319 return;
1320 portp = tty->driver_data;
1321 if (portp == NULL)
1322 return;
1323 stl_startrxtx(portp, -1, 1);
1324}
1325
1326/*****************************************************************************/
1327
Alan Cox606d0992006-12-08 02:38:45 -08001328static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001330 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001331 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
Jiri Slabya0564e12006-12-08 02:38:37 -08001333 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Jiri Slaby615e4a72006-12-08 02:38:38 -08001335 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 return;
1337 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001338 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 return;
1340
1341 tiosp = tty->termios;
1342 if ((tiosp->c_cflag == old->c_cflag) &&
1343 (tiosp->c_iflag == old->c_iflag))
1344 return;
1345
1346 stl_setport(portp, tiosp);
1347 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1348 -1);
1349 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1350 tty->hw_stopped = 0;
1351 stl_start(tty);
1352 }
1353 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
1354 wake_up_interruptible(&portp->open_wait);
1355}
1356
1357/*****************************************************************************/
1358
1359/*
1360 * Attempt to flow control who ever is sending us data. Based on termios
1361 * settings use software or/and hardware flow control.
1362 */
1363
1364static void stl_throttle(struct tty_struct *tty)
1365{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001366 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Jiri Slabya0564e12006-12-08 02:38:37 -08001368 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slaby615e4a72006-12-08 02:38:38 -08001370 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return;
1372 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001373 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return;
1375 stl_flowctrl(portp, 0);
1376}
1377
1378/*****************************************************************************/
1379
1380/*
1381 * Unflow control the device sending us data...
1382 */
1383
1384static void stl_unthrottle(struct tty_struct *tty)
1385{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001386 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Jiri Slabya0564e12006-12-08 02:38:37 -08001388 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Jiri Slaby615e4a72006-12-08 02:38:38 -08001390 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 return;
1392 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001393 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return;
1395 stl_flowctrl(portp, 1);
1396}
1397
1398/*****************************************************************************/
1399
1400/*
1401 * Stop the transmitter. Basically to do this we will just turn TX
1402 * interrupts off.
1403 */
1404
1405static void stl_stop(struct tty_struct *tty)
1406{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001407 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408
Jiri Slabya0564e12006-12-08 02:38:37 -08001409 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Jiri Slaby615e4a72006-12-08 02:38:38 -08001411 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 return;
1413 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001414 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return;
1416 stl_startrxtx(portp, -1, 0);
1417}
1418
1419/*****************************************************************************/
1420
1421/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 * Hangup this port. This is pretty much like closing the port, only
1423 * a little more brutal. No waiting for data to drain. Shutdown the
1424 * port and maybe drop signals.
1425 */
1426
1427static void stl_hangup(struct tty_struct *tty)
1428{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001429 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Jiri Slabya0564e12006-12-08 02:38:37 -08001431 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Jiri Slaby615e4a72006-12-08 02:38:38 -08001433 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 return;
1435 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001436 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return;
1438
1439 portp->flags &= ~ASYNC_INITIALIZED;
1440 stl_disableintrs(portp);
1441 if (tty->termios->c_cflag & HUPCL)
1442 stl_setsignals(portp, 0, 0);
1443 stl_enablerxtx(portp, 0, 0);
1444 stl_flushbuffer(tty);
1445 portp->istate = 0;
1446 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001447 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001449 portp->tx.buf = NULL;
1450 portp->tx.head = NULL;
1451 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 }
Jiri Slaby615e4a72006-12-08 02:38:38 -08001453 portp->tty = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 portp->flags &= ~ASYNC_NORMAL_ACTIVE;
1455 portp->refcount = 0;
1456 wake_up_interruptible(&portp->open_wait);
1457}
1458
1459/*****************************************************************************/
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461static void stl_breakctl(struct tty_struct *tty, int state)
1462{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001463 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Jiri Slabya0564e12006-12-08 02:38:37 -08001465 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jiri Slaby615e4a72006-12-08 02:38:38 -08001467 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 return;
1469 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001470 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 return;
1472
1473 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
1474}
1475
1476/*****************************************************************************/
1477
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478static void stl_sendxchar(struct tty_struct *tty, char ch)
1479{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001480 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Jiri Slabya0564e12006-12-08 02:38:37 -08001482 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
Jiri Slaby615e4a72006-12-08 02:38:38 -08001484 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 return;
1486 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001487 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 return;
1489
1490 if (ch == STOP_CHAR(tty))
1491 stl_sendflow(portp, 0);
1492 else if (ch == START_CHAR(tty))
1493 stl_sendflow(portp, 1);
1494 else
1495 stl_putchar(tty, ch);
1496}
1497
1498/*****************************************************************************/
1499
1500#define MAXLINE 80
1501
1502/*
1503 * Format info for a specified port. The line is deliberately limited
1504 * to 80 characters. (If it is too long it will be truncated, if too
1505 * short then padded with spaces).
1506 */
1507
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001508static int stl_portinfo(struct stlport *portp, int portnr, char *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
1510 char *sp;
1511 int sigs, cnt;
1512
1513 sp = pos;
1514 sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",
1515 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1516 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1517
1518 if (portp->stats.rxframing)
1519 sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);
1520 if (portp->stats.rxparity)
1521 sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);
1522 if (portp->stats.rxbreaks)
1523 sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);
1524 if (portp->stats.rxoverrun)
1525 sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);
1526
1527 sigs = stl_getsignals(portp);
1528 cnt = sprintf(sp, "%s%s%s%s%s ",
1529 (sigs & TIOCM_RTS) ? "|RTS" : "",
1530 (sigs & TIOCM_CTS) ? "|CTS" : "",
1531 (sigs & TIOCM_DTR) ? "|DTR" : "",
1532 (sigs & TIOCM_CD) ? "|DCD" : "",
1533 (sigs & TIOCM_DSR) ? "|DSR" : "");
1534 *sp = ' ';
1535 sp += cnt;
1536
Jiri Slabyc62429d2006-12-08 02:39:14 -08001537 for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 *sp++ = ' ';
1539 if (cnt >= MAXLINE)
1540 pos[(MAXLINE - 2)] = '+';
1541 pos[(MAXLINE - 1)] = '\n';
1542
Jesper Juhl014c2542006-01-15 02:37:08 +01001543 return MAXLINE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544}
1545
1546/*****************************************************************************/
1547
1548/*
1549 * Port info, read from the /proc file system.
1550 */
1551
1552static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
1553{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001554 struct stlbrd *brdp;
1555 struct stlpanel *panelp;
1556 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001557 unsigned int brdnr, panelnr, portnr;
1558 int totalport, curoff, maxoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 char *pos;
1560
Jiri Slabya0564e12006-12-08 02:38:37 -08001561 pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p,"
1562 "data=%p\n", page, start, off, count, eof, data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
1564 pos = page;
1565 totalport = 0;
1566 curoff = 0;
1567
1568 if (off == 0) {
1569 pos += sprintf(pos, "%s: version %s", stl_drvtitle,
1570 stl_drvversion);
1571 while (pos < (page + MAXLINE - 1))
1572 *pos++ = ' ';
1573 *pos++ = '\n';
1574 }
1575 curoff = MAXLINE;
1576
1577/*
1578 * We scan through for each board, panel and port. The offset is
1579 * calculated on the fly, and irrelevant ports are skipped.
1580 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001581 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001583 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 continue;
1585 if (brdp->state == 0)
1586 continue;
1587
1588 maxoff = curoff + (brdp->nrports * MAXLINE);
1589 if (off >= maxoff) {
1590 curoff = maxoff;
1591 continue;
1592 }
1593
1594 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001595 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001597 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 continue;
1599
1600 maxoff = curoff + (panelp->nrports * MAXLINE);
1601 if (off >= maxoff) {
1602 curoff = maxoff;
1603 totalport += panelp->nrports;
1604 continue;
1605 }
1606
Jiri Slabyc62429d2006-12-08 02:39:14 -08001607 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 totalport++) {
1609 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001610 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 continue;
1612 if (off >= (curoff += MAXLINE))
1613 continue;
1614 if ((pos - page + MAXLINE) > count)
1615 goto stl_readdone;
1616 pos += stl_portinfo(portp, totalport, pos);
1617 }
1618 }
1619 }
1620
1621 *eof = 1;
1622
1623stl_readdone:
1624 *start = page;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001625 return pos - page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626}
1627
1628/*****************************************************************************/
1629
1630/*
1631 * All board interrupts are vectored through here first. This code then
1632 * calls off to the approrpriate board interrupt handlers.
1633 */
1634
David Howells7d12e782006-10-05 14:55:46 +01001635static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001637 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
Jeff Garzika6f97b22007-10-31 05:20:49 -04001639 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 return IRQ_RETVAL((* brdp->isr)(brdp));
1642}
1643
1644/*****************************************************************************/
1645
1646/*
1647 * Interrupt service routine for EasyIO board types.
1648 */
1649
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001650static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001652 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 unsigned int iobase;
1654 int handled = 0;
1655
Alan Coxb65b5b52006-06-27 02:54:05 -07001656 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 panelp = brdp->panels[0];
1658 iobase = panelp->iobase;
1659 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1660 handled = 1;
1661 (* panelp->isr)(panelp, iobase);
1662 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001663 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 return handled;
1665}
1666
1667/*****************************************************************************/
1668
1669/*
1670 * Interrupt service routine for ECH-AT board types.
1671 */
1672
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001673static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001675 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001676 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 int handled = 0;
1678
1679 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1680
1681 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1682 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001683 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 ioaddr = brdp->bnkstataddr[bnknr];
1685 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1686 panelp = brdp->bnk2panel[bnknr];
1687 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1688 }
1689 }
1690 }
1691
1692 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1693
1694 return handled;
1695}
1696
1697/*****************************************************************************/
1698
1699/*
1700 * Interrupt service routine for ECH-MCA board types.
1701 */
1702
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001703static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001705 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001706 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 int handled = 0;
1708
1709 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1710 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001711 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 ioaddr = brdp->bnkstataddr[bnknr];
1713 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1714 panelp = brdp->bnk2panel[bnknr];
1715 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1716 }
1717 }
1718 }
1719 return handled;
1720}
1721
1722/*****************************************************************************/
1723
1724/*
1725 * Interrupt service routine for ECH-PCI board types.
1726 */
1727
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001728static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001730 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001731 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 int handled = 0;
1733
1734 while (1) {
1735 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001736 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1738 ioaddr = brdp->bnkstataddr[bnknr];
1739 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1740 panelp = brdp->bnk2panel[bnknr];
1741 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1742 recheck++;
1743 handled = 1;
1744 }
1745 }
1746 if (! recheck)
1747 break;
1748 }
1749 return handled;
1750}
1751
1752/*****************************************************************************/
1753
1754/*
1755 * Interrupt service routine for ECH-8/64-PCI board types.
1756 */
1757
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001758static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001760 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001761 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 int handled = 0;
1763
1764 while (inb(brdp->ioctrl) & 0x1) {
1765 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001766 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 ioaddr = brdp->bnkstataddr[bnknr];
1768 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1769 panelp = brdp->bnk2panel[bnknr];
1770 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1771 }
1772 }
1773 }
1774
1775 return handled;
1776}
1777
1778/*****************************************************************************/
1779
1780/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 * Initialize all the ports on a panel.
1782 */
1783
Jiri Slaby705c1862006-12-08 02:39:11 -08001784static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001786 struct stlport *portp;
1787 unsigned int i;
1788 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
Jiri Slabya0564e12006-12-08 02:38:37 -08001790 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
1792 chipmask = stl_panelinit(brdp, panelp);
1793
1794/*
1795 * All UART's are initialized (if found!). Now go through and setup
1796 * each ports data structures.
1797 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001798 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001799 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001800 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001802 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 break;
1804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
1806 portp->magic = STL_PORTMAGIC;
1807 portp->portnr = i;
1808 portp->brdnr = panelp->brdnr;
1809 portp->panelnr = panelp->panelnr;
1810 portp->uartp = panelp->uartp;
1811 portp->clk = brdp->clk;
1812 portp->baud_base = STL_BAUDBASE;
1813 portp->close_delay = STL_CLOSEDELAY;
1814 portp->closing_wait = 30 * HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 init_waitqueue_head(&portp->open_wait);
1816 init_waitqueue_head(&portp->close_wait);
1817 portp->stats.brd = portp->brdnr;
1818 portp->stats.panel = portp->panelnr;
1819 portp->stats.port = portp->portnr;
1820 panelp->ports[i] = portp;
1821 stl_portinit(brdp, panelp, portp);
1822 }
1823
Jiri Slabyc62429d2006-12-08 02:39:14 -08001824 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825}
1826
Jiri Slaby3b85b342006-12-08 02:39:10 -08001827static void stl_cleanup_panels(struct stlbrd *brdp)
1828{
1829 struct stlpanel *panelp;
1830 struct stlport *portp;
1831 unsigned int j, k;
1832
1833 for (j = 0; j < STL_MAXPANELS; j++) {
1834 panelp = brdp->panels[j];
1835 if (panelp == NULL)
1836 continue;
1837 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1838 portp = panelp->ports[k];
1839 if (portp == NULL)
1840 continue;
1841 if (portp->tty != NULL)
1842 stl_hangup(portp->tty);
1843 kfree(portp->tx.buf);
1844 kfree(portp);
1845 }
1846 kfree(panelp);
1847 }
1848}
1849
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850/*****************************************************************************/
1851
1852/*
1853 * Try to find and initialize an EasyIO board.
1854 */
1855
Jiri Slaby705c1862006-12-08 02:39:11 -08001856static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001858 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 unsigned int status;
1860 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001861 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Jiri Slabya0564e12006-12-08 02:38:37 -08001863 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
1865 brdp->ioctrl = brdp->ioaddr1 + 1;
1866 brdp->iostatus = brdp->ioaddr1 + 2;
1867
1868 status = inb(brdp->iostatus);
1869 if ((status & EIO_IDBITMASK) == EIO_MK3)
1870 brdp->ioctrl++;
1871
1872/*
1873 * Handle board specific stuff now. The real difference is PCI
1874 * or not PCI.
1875 */
1876 if (brdp->brdtype == BRD_EASYIOPCI) {
1877 brdp->iosize1 = 0x80;
1878 brdp->iosize2 = 0x80;
1879 name = "serial(EIO-PCI)";
1880 outb(0x41, (brdp->ioaddr2 + 0x4c));
1881 } else {
1882 brdp->iosize1 = 8;
1883 name = "serial(EIO)";
1884 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1885 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1886 printk("STALLION: invalid irq=%d for brd=%d\n",
1887 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001888 retval = -EINVAL;
1889 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 }
1891 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1892 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1893 brdp->ioctrl);
1894 }
1895
Jiri Slaby3b85b342006-12-08 02:39:10 -08001896 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1898 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1899 "%x conflicts with another device\n", brdp->brdnr,
1900 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001901 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 }
1903
1904 if (brdp->iosize2 > 0)
1905 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1906 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1907 "address %x conflicts with another device\n",
1908 brdp->brdnr, brdp->ioaddr2);
1909 printk(KERN_WARNING "STALLION: Warning, also "
1910 "releasing board %d I/O address %x \n",
1911 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001912 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 }
1914
1915/*
1916 * Everything looks OK, so let's go ahead and probe for the hardware.
1917 */
1918 brdp->clk = CD1400_CLK;
1919 brdp->isr = stl_eiointr;
1920
Jiri Slaby3b85b342006-12-08 02:39:10 -08001921 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 switch (status & EIO_IDBITMASK) {
1923 case EIO_8PORTM:
1924 brdp->clk = CD1400_CLK8M;
1925 /* fall thru */
1926 case EIO_8PORTRS:
1927 case EIO_8PORTDI:
1928 brdp->nrports = 8;
1929 break;
1930 case EIO_4PORTRS:
1931 brdp->nrports = 4;
1932 break;
1933 case EIO_MK3:
1934 switch (status & EIO_BRDMASK) {
1935 case ID_BRD4:
1936 brdp->nrports = 4;
1937 break;
1938 case ID_BRD8:
1939 brdp->nrports = 8;
1940 break;
1941 case ID_BRD16:
1942 brdp->nrports = 16;
1943 break;
1944 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001945 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 }
1947 break;
1948 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001949 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 }
1951
1952/*
1953 * We have verified that the board is actually present, so now we
1954 * can complete the setup.
1955 */
1956
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001957 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001958 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001960 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001961 retval = -ENOMEM;
1962 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964
1965 panelp->magic = STL_PANELMAGIC;
1966 panelp->brdnr = brdp->brdnr;
1967 panelp->panelnr = 0;
1968 panelp->nrports = brdp->nrports;
1969 panelp->iobase = brdp->ioaddr1;
1970 panelp->hwid = status;
1971 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001972 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 panelp->isr = stl_sc26198intr;
1974 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001975 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 panelp->isr = stl_cd1400eiointr;
1977 }
1978
1979 brdp->panels[0] = panelp;
1980 brdp->nrpanels = 1;
1981 brdp->state |= BRD_FOUND;
1982 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001983 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 printk("STALLION: failed to register interrupt "
1985 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001986 retval = -ENODEV;
1987 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001989
1990 return 0;
1991err_fr:
1992 stl_cleanup_panels(brdp);
1993err_rel2:
1994 if (brdp->iosize2 > 0)
1995 release_region(brdp->ioaddr2, brdp->iosize2);
1996err_rel1:
1997 release_region(brdp->ioaddr1, brdp->iosize1);
1998err:
1999 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000}
2001
2002/*****************************************************************************/
2003
2004/*
2005 * Try to find an ECH board and initialize it. This code is capable of
2006 * dealing with all types of ECH board.
2007 */
2008
Jiri Slaby705c1862006-12-08 02:39:11 -08002009static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002011 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002012 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
2013 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 char *name;
2015
Jiri Slabya0564e12006-12-08 02:38:37 -08002016 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
2018 status = 0;
2019 conflict = 0;
2020
2021/*
2022 * Set up the initial board register contents for boards. This varies a
2023 * bit between the different board types. So we need to handle each
2024 * separately. Also do a check that the supplied IRQ is good.
2025 */
2026 switch (brdp->brdtype) {
2027
2028 case BRD_ECH:
2029 brdp->isr = stl_echatintr;
2030 brdp->ioctrl = brdp->ioaddr1 + 1;
2031 brdp->iostatus = brdp->ioaddr1 + 1;
2032 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002033 if ((status & ECH_IDBITMASK) != ECH_ID) {
2034 retval = -ENODEV;
2035 goto err;
2036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2038 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2039 printk("STALLION: invalid irq=%d for brd=%d\n",
2040 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002041 retval = -EINVAL;
2042 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 }
2044 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
2045 status |= (stl_vecmap[brdp->irq] << 1);
2046 outb((status | ECH_BRDRESET), brdp->ioaddr1);
2047 brdp->ioctrlval = ECH_INTENABLE |
2048 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002049 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
2051 brdp->iosize1 = 2;
2052 brdp->iosize2 = 32;
2053 name = "serial(EC8/32)";
2054 outb(status, brdp->ioaddr1);
2055 break;
2056
2057 case BRD_ECHMC:
2058 brdp->isr = stl_echmcaintr;
2059 brdp->ioctrl = brdp->ioaddr1 + 0x20;
2060 brdp->iostatus = brdp->ioctrl;
2061 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002062 if ((status & ECH_IDBITMASK) != ECH_ID) {
2063 retval = -ENODEV;
2064 goto err;
2065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 if ((brdp->irq < 0) || (brdp->irq > 15) ||
2067 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
2068 printk("STALLION: invalid irq=%d for brd=%d\n",
2069 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002070 retval = -EINVAL;
2071 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 }
2073 outb(ECHMC_BRDRESET, brdp->ioctrl);
2074 outb(ECHMC_INTENABLE, brdp->ioctrl);
2075 brdp->iosize1 = 64;
2076 name = "serial(EC8/32-MC)";
2077 break;
2078
2079 case BRD_ECHPCI:
2080 brdp->isr = stl_echpciintr;
2081 brdp->ioctrl = brdp->ioaddr1 + 2;
2082 brdp->iosize1 = 4;
2083 brdp->iosize2 = 8;
2084 name = "serial(EC8/32-PCI)";
2085 break;
2086
2087 case BRD_ECH64PCI:
2088 brdp->isr = stl_echpci64intr;
2089 brdp->ioctrl = brdp->ioaddr2 + 0x40;
2090 outb(0x43, (brdp->ioaddr1 + 0x4c));
2091 brdp->iosize1 = 0x80;
2092 brdp->iosize2 = 0x80;
2093 name = "serial(EC8/64-PCI)";
2094 break;
2095
2096 default:
2097 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002098 retval = -EINVAL;
2099 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 }
2101
2102/*
2103 * Check boards for possible IO address conflicts and return fail status
2104 * if an IO conflict found.
2105 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08002106 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
2108 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
2109 "%x conflicts with another device\n", brdp->brdnr,
2110 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002111 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 }
2113
2114 if (brdp->iosize2 > 0)
2115 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
2116 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
2117 "address %x conflicts with another device\n",
2118 brdp->brdnr, brdp->ioaddr2);
2119 printk(KERN_WARNING "STALLION: Warning, also "
2120 "releasing board %d I/O address %x \n",
2121 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002122 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 }
2124
2125/*
2126 * Scan through the secondary io address space looking for panels.
2127 * As we find'em allocate and initialize panel structures for each.
2128 */
2129 brdp->clk = CD1400_CLK;
2130 brdp->hwid = status;
2131
2132 ioaddr = brdp->ioaddr2;
2133 banknr = 0;
2134 panelnr = 0;
2135 nxtid = 0;
2136
Jiri Slabyc62429d2006-12-08 02:39:14 -08002137 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 if (brdp->brdtype == BRD_ECHPCI) {
2139 outb(nxtid, brdp->ioctrl);
2140 ioaddr = brdp->ioaddr2;
2141 }
2142 status = inb(ioaddr + ECH_PNLSTATUS);
2143 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002144 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002145 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002146 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002148 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002149 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002150 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 panelp->magic = STL_PANELMAGIC;
2153 panelp->brdnr = brdp->brdnr;
2154 panelp->panelnr = panelnr;
2155 panelp->iobase = ioaddr;
2156 panelp->pagenr = nxtid;
2157 panelp->hwid = status;
2158 brdp->bnk2panel[banknr] = panelp;
2159 brdp->bnkpageaddr[banknr] = nxtid;
2160 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2161
2162 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002163 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 panelp->isr = stl_sc26198intr;
2165 if (status & ECH_PNL16PORT) {
2166 panelp->nrports = 16;
2167 brdp->bnk2panel[banknr] = panelp;
2168 brdp->bnkpageaddr[banknr] = nxtid;
2169 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2170 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002171 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002174 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 panelp->isr = stl_cd1400echintr;
2176 if (status & ECH_PNL16PORT) {
2177 panelp->nrports = 16;
2178 panelp->ackmask = 0x80;
2179 if (brdp->brdtype != BRD_ECHPCI)
2180 ioaddr += EREG_BANKSIZE;
2181 brdp->bnk2panel[banknr] = panelp;
2182 brdp->bnkpageaddr[banknr] = ++nxtid;
2183 brdp->bnkstataddr[banknr++] = ioaddr +
2184 ECH_PNLSTATUS;
2185 } else {
2186 panelp->nrports = 8;
2187 panelp->ackmask = 0xc0;
2188 }
2189 }
2190
2191 nxtid++;
2192 ioaddr += EREG_BANKSIZE;
2193 brdp->nrports += panelp->nrports;
2194 brdp->panels[panelnr++] = panelp;
2195 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002196 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2197 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002198 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 }
2201
2202 brdp->nrpanels = panelnr;
2203 brdp->nrbnks = banknr;
2204 if (brdp->brdtype == BRD_ECH)
2205 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2206
2207 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002208 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 printk("STALLION: failed to register interrupt "
2210 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002211 retval = -ENODEV;
2212 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 }
2214
Jiri Slaby3b85b342006-12-08 02:39:10 -08002215 return 0;
2216err_fr:
2217 stl_cleanup_panels(brdp);
2218 if (brdp->iosize2 > 0)
2219 release_region(brdp->ioaddr2, brdp->iosize2);
2220err_rel1:
2221 release_region(brdp->ioaddr1, brdp->iosize1);
2222err:
2223 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224}
2225
2226/*****************************************************************************/
2227
2228/*
2229 * Initialize and configure the specified board.
2230 * Scan through all the boards in the configuration and see what we
2231 * can find. Handle EIO and the ECH boards a little differently here
2232 * since the initial search and setup is very different.
2233 */
2234
Jiri Slaby705c1862006-12-08 02:39:11 -08002235static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002237 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Jiri Slabya0564e12006-12-08 02:38:37 -08002239 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 switch (brdp->brdtype) {
2242 case BRD_EASYIO:
2243 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002244 retval = stl_initeio(brdp);
2245 if (retval)
2246 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 break;
2248 case BRD_ECH:
2249 case BRD_ECHMC:
2250 case BRD_ECHPCI:
2251 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002252 retval = stl_initech(brdp);
2253 if (retval)
2254 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 break;
2256 default:
2257 printk("STALLION: board=%d is unknown board type=%d\n",
2258 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002259 retval = -ENODEV;
2260 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 }
2262
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 if ((brdp->state & BRD_FOUND) == 0) {
2264 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2265 stl_brdnames[brdp->brdtype], brdp->brdnr,
2266 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002267 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 }
2269
Jiri Slabyc62429d2006-12-08 02:39:14 -08002270 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002271 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 stl_initports(brdp, brdp->panels[i]);
2273
2274 printk("STALLION: %s found, board=%d io=%x irq=%d "
2275 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2276 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2277 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002278
2279 return 0;
2280err_free:
2281 free_irq(brdp->irq, brdp);
2282
2283 stl_cleanup_panels(brdp);
2284
2285 release_region(brdp->ioaddr1, brdp->iosize1);
2286 if (brdp->iosize2 > 0)
2287 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002288err:
2289 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290}
2291
2292/*****************************************************************************/
2293
2294/*
2295 * Find the next available board number that is free.
2296 */
2297
Jiri Slaby705c1862006-12-08 02:39:11 -08002298static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002300 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
Jiri Slabyc62429d2006-12-08 02:39:14 -08002302 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002303 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 if (i >= stl_nrbrds)
2305 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002306 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002308
2309 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310}
2311
2312/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313/*
2314 * We have a Stallion board. Allocate a board structure and
2315 * initialize it. Read its IO and IRQ resources from PCI
2316 * configuration space.
2317 */
2318
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002319static int __devinit stl_pciprobe(struct pci_dev *pdev,
2320 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002322 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002323 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002324 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002326 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002327 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002328
Jiri Slaby3b85b342006-12-08 02:39:10 -08002329 retval = pci_enable_device(pdev);
2330 if (retval)
2331 goto err;
2332 brdp = stl_allocbrd();
2333 if (brdp == NULL) {
2334 retval = -ENOMEM;
2335 goto err;
2336 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002337 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002338 brdnr = stl_getbrdnr();
2339 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002340 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002342 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002343 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002344 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002346 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002347 stl_brds[brdp->brdnr] = brdp;
2348 mutex_unlock(&stl_brdslock);
2349
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002351 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
2353/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 * We have all resources from the board, so let's setup the actual
2355 * board structure now.
2356 */
2357 switch (brdtype) {
2358 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002359 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2360 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 break;
2362 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002363 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2364 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 break;
2366 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002367 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2368 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 break;
2370 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002371 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 break;
2373 }
2374
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002375 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002376 retval = stl_brdinit(brdp);
2377 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002378 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002380 pci_set_drvdata(pdev, brdp);
2381
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002382 for (i = 0; i < brdp->nrports; i++)
2383 tty_register_device(stl_serial,
2384 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2385
Jiri Slaby3b85b342006-12-08 02:39:10 -08002386 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002387err_null:
2388 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002389err_fr:
2390 kfree(brdp);
2391err:
2392 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393}
2394
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002395static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002397 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002398 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002400 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002402 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002404 release_region(brdp->ioaddr1, brdp->iosize1);
2405 if (brdp->iosize2 > 0)
2406 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002408 for (i = 0; i < brdp->nrports; i++)
2409 tty_unregister_device(stl_serial,
2410 brdp->brdnr * STL_MAXPORTS + i);
2411
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002412 stl_brds[brdp->brdnr] = NULL;
2413 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414}
2415
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002416static struct pci_driver stl_pcidriver = {
2417 .name = "stallion",
2418 .id_table = stl_pcibrds,
2419 .probe = stl_pciprobe,
2420 .remove = __devexit_p(stl_pciremove)
2421};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
2423/*****************************************************************************/
2424
2425/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 * Return the board stats structure to user app.
2427 */
2428
2429static int stl_getbrdstats(combrd_t __user *bp)
2430{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002431 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002432 struct stlbrd *brdp;
2433 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002434 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
2436 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2437 return -EFAULT;
2438 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002439 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002441 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002442 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
2444 memset(&stl_brdstats, 0, sizeof(combrd_t));
2445 stl_brdstats.brd = brdp->brdnr;
2446 stl_brdstats.type = brdp->brdtype;
2447 stl_brdstats.hwid = brdp->hwid;
2448 stl_brdstats.state = brdp->state;
2449 stl_brdstats.ioaddr = brdp->ioaddr1;
2450 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2451 stl_brdstats.irq = brdp->irq;
2452 stl_brdstats.nrpanels = brdp->nrpanels;
2453 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002454 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 panelp = brdp->panels[i];
2456 stl_brdstats.panels[i].panel = i;
2457 stl_brdstats.panels[i].hwid = panelp->hwid;
2458 stl_brdstats.panels[i].nrports = panelp->nrports;
2459 }
2460
2461 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2462}
2463
2464/*****************************************************************************/
2465
2466/*
2467 * Resolve the referenced port number into a port struct pointer.
2468 */
2469
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002470static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002472 struct stlbrd *brdp;
2473 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Jiri Slabyc62429d2006-12-08 02:39:14 -08002475 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2476 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002478 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002479 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002480 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002481 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002483 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002484 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002485 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002486 return NULL;
2487 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488}
2489
2490/*****************************************************************************/
2491
2492/*
2493 * Return the port stats structure to user app. A NULL port struct
2494 * pointer passed in means that we need to find out from the app
2495 * what port to get stats for (used through board control device).
2496 */
2497
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002498static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002500 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 unsigned char *head, *tail;
2502 unsigned long flags;
2503
2504 if (!portp) {
2505 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2506 return -EFAULT;
2507 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2508 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002509 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002510 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 }
2512
2513 portp->stats.state = portp->istate;
2514 portp->stats.flags = portp->flags;
2515 portp->stats.hwid = portp->hwid;
2516
2517 portp->stats.ttystate = 0;
2518 portp->stats.cflags = 0;
2519 portp->stats.iflags = 0;
2520 portp->stats.oflags = 0;
2521 portp->stats.lflags = 0;
2522 portp->stats.rxbuffered = 0;
2523
Alan Coxb65b5b52006-06-27 02:54:05 -07002524 spin_lock_irqsave(&stallion_lock, flags);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002525 if (portp->tty != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 if (portp->tty->driver_data == portp) {
2527 portp->stats.ttystate = portp->tty->flags;
Alan Cox33f0f882006-01-09 20:54:13 -08002528 /* No longer available as a statistic */
2529 portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
Jiri Slaby615e4a72006-12-08 02:38:38 -08002530 if (portp->tty->termios != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 portp->stats.cflags = portp->tty->termios->c_cflag;
2532 portp->stats.iflags = portp->tty->termios->c_iflag;
2533 portp->stats.oflags = portp->tty->termios->c_oflag;
2534 portp->stats.lflags = portp->tty->termios->c_lflag;
2535 }
2536 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002537 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
2539 head = portp->tx.head;
2540 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002541 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2542 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
2544 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2545
2546 return copy_to_user(cp, &portp->stats,
2547 sizeof(comstats_t)) ? -EFAULT : 0;
2548}
2549
2550/*****************************************************************************/
2551
2552/*
2553 * Clear the port stats structure. We also return it zeroed out...
2554 */
2555
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002556static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002558 comstats_t stl_comstats;
2559
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 if (!portp) {
2561 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2562 return -EFAULT;
2563 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2564 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002565 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002566 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 }
2568
2569 memset(&portp->stats, 0, sizeof(comstats_t));
2570 portp->stats.brd = portp->brdnr;
2571 portp->stats.panel = portp->panelnr;
2572 portp->stats.port = portp->portnr;
2573 return copy_to_user(cp, &portp->stats,
2574 sizeof(comstats_t)) ? -EFAULT : 0;
2575}
2576
2577/*****************************************************************************/
2578
2579/*
2580 * Return the entire driver ports structure to a user app.
2581 */
2582
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002583static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002585 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002586 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002588 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 return -EFAULT;
2590 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2591 stl_dummyport.portnr);
2592 if (!portp)
2593 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002594 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595}
2596
2597/*****************************************************************************/
2598
2599/*
2600 * Return the entire driver board structure to a user app.
2601 */
2602
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002603static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002605 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002606 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002608 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002610 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 return -ENODEV;
2612 brdp = stl_brds[stl_dummybrd.brdnr];
2613 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002614 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002615 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616}
2617
2618/*****************************************************************************/
2619
2620/*
2621 * The "staliomem" device is also required to do some special operations
2622 * on the board and/or ports. In this driver it is mostly used for stats
2623 * collection.
2624 */
2625
2626static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2627{
2628 int brdnr, rc;
2629 void __user *argp = (void __user *)arg;
2630
Jiri Slabya0564e12006-12-08 02:38:37 -08002631 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
2633 brdnr = iminor(ip);
2634 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002635 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 rc = 0;
2637
2638 switch (cmd) {
2639 case COM_GETPORTSTATS:
2640 rc = stl_getportstats(NULL, argp);
2641 break;
2642 case COM_CLRPORTSTATS:
2643 rc = stl_clrportstats(NULL, argp);
2644 break;
2645 case COM_GETBRDSTATS:
2646 rc = stl_getbrdstats(argp);
2647 break;
2648 case COM_READPORT:
2649 rc = stl_getportstruct(argp);
2650 break;
2651 case COM_READBOARD:
2652 rc = stl_getbrdstruct(argp);
2653 break;
2654 default:
2655 rc = -ENOIOCTLCMD;
2656 break;
2657 }
2658
Jiri Slabyc62429d2006-12-08 02:39:14 -08002659 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660}
2661
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002662static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 .open = stl_open,
2664 .close = stl_close,
2665 .write = stl_write,
2666 .put_char = stl_putchar,
2667 .flush_chars = stl_flushchars,
2668 .write_room = stl_writeroom,
2669 .chars_in_buffer = stl_charsinbuffer,
2670 .ioctl = stl_ioctl,
2671 .set_termios = stl_settermios,
2672 .throttle = stl_throttle,
2673 .unthrottle = stl_unthrottle,
2674 .stop = stl_stop,
2675 .start = stl_start,
2676 .hangup = stl_hangup,
2677 .flush_buffer = stl_flushbuffer,
2678 .break_ctl = stl_breakctl,
2679 .wait_until_sent = stl_waituntilsent,
2680 .send_xchar = stl_sendxchar,
2681 .read_proc = stl_readproc,
2682 .tiocmget = stl_tiocmget,
2683 .tiocmset = stl_tiocmset,
2684};
2685
2686/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687/* CD1400 HARDWARE FUNCTIONS */
2688/*****************************************************************************/
2689
2690/*
2691 * These functions get/set/update the registers of the cd1400 UARTs.
2692 * Access to the cd1400 registers is via an address/data io port pair.
2693 * (Maybe should make this inline...)
2694 */
2695
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002696static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697{
2698 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002699 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700}
2701
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002702static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002704 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 outb(value, portp->ioaddr + EREG_DATA);
2706}
2707
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002708static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002710 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 if (inb(portp->ioaddr + EREG_DATA) != value) {
2712 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002713 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002715 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716}
2717
2718/*****************************************************************************/
2719
2720/*
2721 * Inbitialize the UARTs in a panel. We don't care what sort of board
2722 * these ports are on - since the port io registers are almost
2723 * identical when dealing with ports.
2724 */
2725
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002726static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727{
2728 unsigned int gfrcr;
2729 int chipmask, i, j;
2730 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002731 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
Jiri Slabya0564e12006-12-08 02:38:37 -08002733 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734
Alan Coxb65b5b52006-06-27 02:54:05 -07002735 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 BRDENABLE(panelp->brdnr, panelp->pagenr);
2737
2738/*
2739 * Check that each chip is present and started up OK.
2740 */
2741 chipmask = 0;
2742 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002743 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 if (brdp->brdtype == BRD_ECHPCI) {
2745 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2746 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002747 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 uartaddr = (i & 0x01) ? 0x080 : 0;
2750 outb((GFRCR + uartaddr), ioaddr);
2751 outb(0, (ioaddr + EREG_DATA));
2752 outb((CCR + uartaddr), ioaddr);
2753 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2754 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2755 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002756 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2758 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002759
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2761 printk("STALLION: cd1400 not responding, "
2762 "brd=%d panel=%d chip=%d\n",
2763 panelp->brdnr, panelp->panelnr, i);
2764 continue;
2765 }
2766 chipmask |= (0x1 << i);
2767 outb((PPR + uartaddr), ioaddr);
2768 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2769 }
2770
2771 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002772 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002773 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774}
2775
2776/*****************************************************************************/
2777
2778/*
2779 * Initialize hardware specific port registers.
2780 */
2781
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002782static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783{
Alan Coxb65b5b52006-06-27 02:54:05 -07002784 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002785 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2786 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787
Jiri Slaby615e4a72006-12-08 02:38:38 -08002788 if ((brdp == NULL) || (panelp == NULL) ||
2789 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return;
2791
Alan Coxb65b5b52006-06-27 02:54:05 -07002792 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2794 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2795 portp->uartaddr = (portp->portnr & 0x04) << 5;
2796 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2797
2798 BRDENABLE(portp->brdnr, portp->pagenr);
2799 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2800 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2801 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2802 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002803 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804}
2805
2806/*****************************************************************************/
2807
2808/*
2809 * Wait for the command register to be ready. We will poll this,
2810 * since it won't usually take too long to be ready.
2811 */
2812
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002813static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
2815 int i;
2816
Jiri Slabyc62429d2006-12-08 02:39:14 -08002817 for (i = 0; i < CCR_MAXWAIT; i++)
2818 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
2821 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2822 portp->portnr, portp->panelnr, portp->brdnr);
2823}
2824
2825/*****************************************************************************/
2826
2827/*
2828 * Set up the cd1400 registers for a port based on the termios port
2829 * settings.
2830 */
2831
Alan Cox606d0992006-12-08 02:38:45 -08002832static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002834 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 unsigned long flags;
2836 unsigned int clkdiv, baudrate;
2837 unsigned char cor1, cor2, cor3;
2838 unsigned char cor4, cor5, ccr;
2839 unsigned char srer, sreron, sreroff;
2840 unsigned char mcor1, mcor2, rtpr;
2841 unsigned char clk, div;
2842
2843 cor1 = 0;
2844 cor2 = 0;
2845 cor3 = 0;
2846 cor4 = 0;
2847 cor5 = 0;
2848 ccr = 0;
2849 rtpr = 0;
2850 clk = 0;
2851 div = 0;
2852 mcor1 = 0;
2853 mcor2 = 0;
2854 sreron = 0;
2855 sreroff = 0;
2856
2857 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002858 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 return;
2860
2861/*
2862 * Set up the RX char ignore mask with those RX error types we
2863 * can ignore. We can get the cd1400 to help us out a little here,
2864 * it will ignore parity errors and breaks for us.
2865 */
2866 portp->rxignoremsk = 0;
2867 if (tiosp->c_iflag & IGNPAR) {
2868 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2869 cor1 |= COR1_PARIGNORE;
2870 }
2871 if (tiosp->c_iflag & IGNBRK) {
2872 portp->rxignoremsk |= ST_BREAK;
2873 cor4 |= COR4_IGNBRK;
2874 }
2875
2876 portp->rxmarkmsk = ST_OVERRUN;
2877 if (tiosp->c_iflag & (INPCK | PARMRK))
2878 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2879 if (tiosp->c_iflag & BRKINT)
2880 portp->rxmarkmsk |= ST_BREAK;
2881
2882/*
2883 * Go through the char size, parity and stop bits and set all the
2884 * option register appropriately.
2885 */
2886 switch (tiosp->c_cflag & CSIZE) {
2887 case CS5:
2888 cor1 |= COR1_CHL5;
2889 break;
2890 case CS6:
2891 cor1 |= COR1_CHL6;
2892 break;
2893 case CS7:
2894 cor1 |= COR1_CHL7;
2895 break;
2896 default:
2897 cor1 |= COR1_CHL8;
2898 break;
2899 }
2900
2901 if (tiosp->c_cflag & CSTOPB)
2902 cor1 |= COR1_STOP2;
2903 else
2904 cor1 |= COR1_STOP1;
2905
2906 if (tiosp->c_cflag & PARENB) {
2907 if (tiosp->c_cflag & PARODD)
2908 cor1 |= (COR1_PARENB | COR1_PARODD);
2909 else
2910 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2911 } else {
2912 cor1 |= COR1_PARNONE;
2913 }
2914
2915/*
2916 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2917 * space for hardware flow control and the like. This should be set to
2918 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2919 * really be based on VTIME.
2920 */
2921 cor3 |= FIFO_RXTHRESHOLD;
2922 rtpr = 2;
2923
2924/*
2925 * Calculate the baud rate timers. For now we will just assume that
2926 * the input and output baud are the same. Could have used a baud
2927 * table here, but this way we can generate virtually any baud rate
2928 * we like!
2929 */
2930 baudrate = tiosp->c_cflag & CBAUD;
2931 if (baudrate & CBAUDEX) {
2932 baudrate &= ~CBAUDEX;
2933 if ((baudrate < 1) || (baudrate > 4))
2934 tiosp->c_cflag &= ~CBAUDEX;
2935 else
2936 baudrate += 15;
2937 }
2938 baudrate = stl_baudrates[baudrate];
2939 if ((tiosp->c_cflag & CBAUD) == B38400) {
2940 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
2941 baudrate = 57600;
2942 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
2943 baudrate = 115200;
2944 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
2945 baudrate = 230400;
2946 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
2947 baudrate = 460800;
2948 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
2949 baudrate = (portp->baud_base / portp->custom_divisor);
2950 }
2951 if (baudrate > STL_CD1400MAXBAUD)
2952 baudrate = STL_CD1400MAXBAUD;
2953
2954 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002955 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2956 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 if (clkdiv < 0x100)
2958 break;
2959 }
2960 div = (unsigned char) clkdiv;
2961 }
2962
2963/*
2964 * Check what form of modem signaling is required and set it up.
2965 */
2966 if ((tiosp->c_cflag & CLOCAL) == 0) {
2967 mcor1 |= MCOR1_DCD;
2968 mcor2 |= MCOR2_DCD;
2969 sreron |= SRER_MODEM;
2970 portp->flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002971 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 portp->flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
2974/*
2975 * Setup cd1400 enhanced modes if we can. In particular we want to
2976 * handle as much of the flow control as possible automatically. As
2977 * well as saving a few CPU cycles it will also greatly improve flow
2978 * control reliability.
2979 */
2980 if (tiosp->c_iflag & IXON) {
2981 cor2 |= COR2_TXIBE;
2982 cor3 |= COR3_SCD12;
2983 if (tiosp->c_iflag & IXANY)
2984 cor2 |= COR2_IXM;
2985 }
2986
2987 if (tiosp->c_cflag & CRTSCTS) {
2988 cor2 |= COR2_CTSAE;
2989 mcor1 |= FIFO_RTSTHRESHOLD;
2990 }
2991
2992/*
2993 * All cd1400 register values calculated so go through and set
2994 * them all up.
2995 */
2996
Jiri Slabya0564e12006-12-08 02:38:37 -08002997 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002999 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08003001 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08003003 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
3004 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3006 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Alan Coxb65b5b52006-06-27 02:54:05 -07003008 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 BRDENABLE(portp->brdnr, portp->pagenr);
3010 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
3011 srer = stl_cd1400getreg(portp, SRER);
3012 stl_cd1400setreg(portp, SRER, 0);
3013 if (stl_cd1400updatereg(portp, COR1, cor1))
3014 ccr = 1;
3015 if (stl_cd1400updatereg(portp, COR2, cor2))
3016 ccr = 1;
3017 if (stl_cd1400updatereg(portp, COR3, cor3))
3018 ccr = 1;
3019 if (ccr) {
3020 stl_cd1400ccrwait(portp);
3021 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
3022 }
3023 stl_cd1400setreg(portp, COR4, cor4);
3024 stl_cd1400setreg(portp, COR5, cor5);
3025 stl_cd1400setreg(portp, MCOR1, mcor1);
3026 stl_cd1400setreg(portp, MCOR2, mcor2);
3027 if (baudrate > 0) {
3028 stl_cd1400setreg(portp, TCOR, clk);
3029 stl_cd1400setreg(portp, TBPR, div);
3030 stl_cd1400setreg(portp, RCOR, clk);
3031 stl_cd1400setreg(portp, RBPR, div);
3032 }
3033 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
3034 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
3035 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
3036 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
3037 stl_cd1400setreg(portp, RTPR, rtpr);
3038 mcor1 = stl_cd1400getreg(portp, MSVR1);
3039 if (mcor1 & MSVR1_DCD)
3040 portp->sigs |= TIOCM_CD;
3041 else
3042 portp->sigs &= ~TIOCM_CD;
3043 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
3044 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003045 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046}
3047
3048/*****************************************************************************/
3049
3050/*
3051 * Set the state of the DTR and RTS signals.
3052 */
3053
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003054static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055{
3056 unsigned char msvr1, msvr2;
3057 unsigned long flags;
3058
Jiri Slabya0564e12006-12-08 02:38:37 -08003059 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
3060 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
3062 msvr1 = 0;
3063 msvr2 = 0;
3064 if (dtr > 0)
3065 msvr1 = MSVR1_DTR;
3066 if (rts > 0)
3067 msvr2 = MSVR2_RTS;
3068
Alan Coxb65b5b52006-06-27 02:54:05 -07003069 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 BRDENABLE(portp->brdnr, portp->pagenr);
3071 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3072 if (rts >= 0)
3073 stl_cd1400setreg(portp, MSVR2, msvr2);
3074 if (dtr >= 0)
3075 stl_cd1400setreg(portp, MSVR1, msvr1);
3076 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003077 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078}
3079
3080/*****************************************************************************/
3081
3082/*
3083 * Return the state of the signals.
3084 */
3085
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003086static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087{
3088 unsigned char msvr1, msvr2;
3089 unsigned long flags;
3090 int sigs;
3091
Jiri Slabya0564e12006-12-08 02:38:37 -08003092 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093
Alan Coxb65b5b52006-06-27 02:54:05 -07003094 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 BRDENABLE(portp->brdnr, portp->pagenr);
3096 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3097 msvr1 = stl_cd1400getreg(portp, MSVR1);
3098 msvr2 = stl_cd1400getreg(portp, MSVR2);
3099 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003100 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101
3102 sigs = 0;
3103 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
3104 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
3105 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
3106 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
3107#if 0
3108 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
3109 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
3110#else
3111 sigs |= TIOCM_DSR;
3112#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01003113 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114}
3115
3116/*****************************************************************************/
3117
3118/*
3119 * Enable/Disable the Transmitter and/or Receiver.
3120 */
3121
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003122static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123{
3124 unsigned char ccr;
3125 unsigned long flags;
3126
Jiri Slabya0564e12006-12-08 02:38:37 -08003127 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
3128
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 ccr = 0;
3130
3131 if (tx == 0)
3132 ccr |= CCR_TXDISABLE;
3133 else if (tx > 0)
3134 ccr |= CCR_TXENABLE;
3135 if (rx == 0)
3136 ccr |= CCR_RXDISABLE;
3137 else if (rx > 0)
3138 ccr |= CCR_RXENABLE;
3139
Alan Coxb65b5b52006-06-27 02:54:05 -07003140 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 BRDENABLE(portp->brdnr, portp->pagenr);
3142 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3143 stl_cd1400ccrwait(portp);
3144 stl_cd1400setreg(portp, CCR, ccr);
3145 stl_cd1400ccrwait(portp);
3146 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003147 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148}
3149
3150/*****************************************************************************/
3151
3152/*
3153 * Start/stop the Transmitter and/or Receiver.
3154 */
3155
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003156static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157{
3158 unsigned char sreron, sreroff;
3159 unsigned long flags;
3160
Jiri Slabya0564e12006-12-08 02:38:37 -08003161 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
3163 sreron = 0;
3164 sreroff = 0;
3165 if (tx == 0)
3166 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3167 else if (tx == 1)
3168 sreron |= SRER_TXDATA;
3169 else if (tx >= 2)
3170 sreron |= SRER_TXEMPTY;
3171 if (rx == 0)
3172 sreroff |= SRER_RXDATA;
3173 else if (rx > 0)
3174 sreron |= SRER_RXDATA;
3175
Alan Coxb65b5b52006-06-27 02:54:05 -07003176 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 BRDENABLE(portp->brdnr, portp->pagenr);
3178 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3179 stl_cd1400setreg(portp, SRER,
3180 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3181 BRDDISABLE(portp->brdnr);
3182 if (tx > 0)
3183 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003184 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185}
3186
3187/*****************************************************************************/
3188
3189/*
3190 * Disable all interrupts from this port.
3191 */
3192
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003193static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194{
3195 unsigned long flags;
3196
Jiri Slabya0564e12006-12-08 02:38:37 -08003197 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3198
Alan Coxb65b5b52006-06-27 02:54:05 -07003199 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 BRDENABLE(portp->brdnr, portp->pagenr);
3201 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3202 stl_cd1400setreg(portp, SRER, 0);
3203 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003204 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205}
3206
3207/*****************************************************************************/
3208
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003209static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210{
3211 unsigned long flags;
3212
Jiri Slabya0564e12006-12-08 02:38:37 -08003213 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214
Alan Coxb65b5b52006-06-27 02:54:05 -07003215 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 BRDENABLE(portp->brdnr, portp->pagenr);
3217 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3218 stl_cd1400setreg(portp, SRER,
3219 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3220 SRER_TXEMPTY));
3221 BRDDISABLE(portp->brdnr);
3222 portp->brklen = len;
3223 if (len == 1)
3224 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003225 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226}
3227
3228/*****************************************************************************/
3229
3230/*
3231 * Take flow control actions...
3232 */
3233
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003234static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235{
3236 struct tty_struct *tty;
3237 unsigned long flags;
3238
Jiri Slabya0564e12006-12-08 02:38:37 -08003239 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240
Jiri Slaby615e4a72006-12-08 02:38:38 -08003241 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 return;
3243 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003244 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 return;
3246
Alan Coxb65b5b52006-06-27 02:54:05 -07003247 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 BRDENABLE(portp->brdnr, portp->pagenr);
3249 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3250
3251 if (state) {
3252 if (tty->termios->c_iflag & IXOFF) {
3253 stl_cd1400ccrwait(portp);
3254 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3255 portp->stats.rxxon++;
3256 stl_cd1400ccrwait(portp);
3257 }
3258/*
3259 * Question: should we return RTS to what it was before? It may
3260 * have been set by an ioctl... Suppose not, since if you have
3261 * hardware flow control set then it is pretty silly to go and
3262 * set the RTS line by hand.
3263 */
3264 if (tty->termios->c_cflag & CRTSCTS) {
3265 stl_cd1400setreg(portp, MCOR1,
3266 (stl_cd1400getreg(portp, MCOR1) |
3267 FIFO_RTSTHRESHOLD));
3268 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3269 portp->stats.rxrtson++;
3270 }
3271 } else {
3272 if (tty->termios->c_iflag & IXOFF) {
3273 stl_cd1400ccrwait(portp);
3274 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3275 portp->stats.rxxoff++;
3276 stl_cd1400ccrwait(portp);
3277 }
3278 if (tty->termios->c_cflag & CRTSCTS) {
3279 stl_cd1400setreg(portp, MCOR1,
3280 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3281 stl_cd1400setreg(portp, MSVR2, 0);
3282 portp->stats.rxrtsoff++;
3283 }
3284 }
3285
3286 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003287 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288}
3289
3290/*****************************************************************************/
3291
3292/*
3293 * Send a flow control character...
3294 */
3295
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003296static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297{
3298 struct tty_struct *tty;
3299 unsigned long flags;
3300
Jiri Slabya0564e12006-12-08 02:38:37 -08003301 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
Jiri Slaby615e4a72006-12-08 02:38:38 -08003303 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304 return;
3305 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08003306 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 return;
3308
Alan Coxb65b5b52006-06-27 02:54:05 -07003309 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 BRDENABLE(portp->brdnr, portp->pagenr);
3311 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3312 if (state) {
3313 stl_cd1400ccrwait(portp);
3314 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3315 portp->stats.rxxon++;
3316 stl_cd1400ccrwait(portp);
3317 } else {
3318 stl_cd1400ccrwait(portp);
3319 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3320 portp->stats.rxxoff++;
3321 stl_cd1400ccrwait(portp);
3322 }
3323 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003324 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325}
3326
3327/*****************************************************************************/
3328
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003329static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330{
3331 unsigned long flags;
3332
Jiri Slabya0564e12006-12-08 02:38:37 -08003333 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
Jiri Slaby615e4a72006-12-08 02:38:38 -08003335 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 return;
3337
Alan Coxb65b5b52006-06-27 02:54:05 -07003338 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 BRDENABLE(portp->brdnr, portp->pagenr);
3340 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3341 stl_cd1400ccrwait(portp);
3342 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3343 stl_cd1400ccrwait(portp);
3344 portp->tx.tail = portp->tx.head;
3345 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003346 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347}
3348
3349/*****************************************************************************/
3350
3351/*
3352 * Return the current state of data flow on this port. This is only
3353 * really interresting when determining if data has fully completed
3354 * transmission or not... This is easy for the cd1400, it accurately
3355 * maintains the busy port flag.
3356 */
3357
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003358static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359{
Jiri Slabya0564e12006-12-08 02:38:37 -08003360 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Jiri Slaby615e4a72006-12-08 02:38:38 -08003362 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003363 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Jesper Juhl014c2542006-01-15 02:37:08 +01003365 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366}
3367
3368/*****************************************************************************/
3369
3370/*
3371 * Interrupt service routine for cd1400 EasyIO boards.
3372 */
3373
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003374static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375{
3376 unsigned char svrtype;
3377
Jiri Slabya0564e12006-12-08 02:38:37 -08003378 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Alan Coxb65b5b52006-06-27 02:54:05 -07003380 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 outb(SVRR, iobase);
3382 svrtype = inb(iobase + EREG_DATA);
3383 if (panelp->nrports > 4) {
3384 outb((SVRR + 0x80), iobase);
3385 svrtype |= inb(iobase + EREG_DATA);
3386 }
3387
3388 if (svrtype & SVRR_RX)
3389 stl_cd1400rxisr(panelp, iobase);
3390 else if (svrtype & SVRR_TX)
3391 stl_cd1400txisr(panelp, iobase);
3392 else if (svrtype & SVRR_MDM)
3393 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003394
3395 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396}
3397
3398/*****************************************************************************/
3399
3400/*
3401 * Interrupt service routine for cd1400 panels.
3402 */
3403
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003404static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405{
3406 unsigned char svrtype;
3407
Jiri Slabya0564e12006-12-08 02:38:37 -08003408 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
3410 outb(SVRR, iobase);
3411 svrtype = inb(iobase + EREG_DATA);
3412 outb((SVRR + 0x80), iobase);
3413 svrtype |= inb(iobase + EREG_DATA);
3414 if (svrtype & SVRR_RX)
3415 stl_cd1400rxisr(panelp, iobase);
3416 else if (svrtype & SVRR_TX)
3417 stl_cd1400txisr(panelp, iobase);
3418 else if (svrtype & SVRR_MDM)
3419 stl_cd1400mdmisr(panelp, iobase);
3420}
3421
3422
3423/*****************************************************************************/
3424
3425/*
3426 * Unfortunately we need to handle breaks in the TX data stream, since
3427 * this is the only way to generate them on the cd1400.
3428 */
3429
Jiri Slaby60be4812006-12-08 02:38:40 -08003430static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431{
3432 if (portp->brklen == 1) {
3433 outb((COR2 + portp->uartaddr), ioaddr);
3434 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3435 (ioaddr + EREG_DATA));
3436 outb((TDR + portp->uartaddr), ioaddr);
3437 outb(ETC_CMD, (ioaddr + EREG_DATA));
3438 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3439 outb((SRER + portp->uartaddr), ioaddr);
3440 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3441 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003442 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 } else if (portp->brklen > 1) {
3444 outb((TDR + portp->uartaddr), ioaddr);
3445 outb(ETC_CMD, (ioaddr + EREG_DATA));
3446 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3447 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003448 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 } else {
3450 outb((COR2 + portp->uartaddr), ioaddr);
3451 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3452 (ioaddr + EREG_DATA));
3453 portp->brklen = 0;
3454 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003455 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456}
3457
3458/*****************************************************************************/
3459
3460/*
3461 * Transmit interrupt handler. This has gotta be fast! Handling TX
3462 * chars is pretty simple, stuff as many as possible from the TX buffer
3463 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3464 * are embedded as commands in the data stream. Oh no, had to use a goto!
3465 * This could be optimized more, will do when I get time...
3466 * In practice it is possible that interrupts are enabled but that the
3467 * port has been hung up. Need to handle not having any TX buffer here,
3468 * this is done by using the side effect that head and tail will also
3469 * be NULL if the buffer has been freed.
3470 */
3471
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003472static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003474 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 int len, stlen;
3476 char *head, *tail;
3477 unsigned char ioack, srer;
3478
Jiri Slabya0564e12006-12-08 02:38:37 -08003479 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480
3481 ioack = inb(ioaddr + EREG_TXACK);
3482 if (((ioack & panelp->ackmask) != 0) ||
3483 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3484 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3485 return;
3486 }
3487 portp = panelp->ports[(ioack >> 3)];
3488
3489/*
3490 * Unfortunately we need to handle breaks in the data stream, since
3491 * this is the only way to generate them on the cd1400. Do it now if
3492 * a break is to be sent.
3493 */
3494 if (portp->brklen != 0)
3495 if (stl_cd1400breakisr(portp, ioaddr))
3496 goto stl_txalldone;
3497
3498 head = portp->tx.head;
3499 tail = portp->tx.tail;
3500 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3501 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3502 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3503 set_bit(ASYI_TXLOW, &portp->istate);
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003504 if (portp->tty)
3505 tty_wakeup(portp->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 }
3507
3508 if (len == 0) {
3509 outb((SRER + portp->uartaddr), ioaddr);
3510 srer = inb(ioaddr + EREG_DATA);
3511 if (srer & SRER_TXDATA) {
3512 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3513 } else {
3514 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3515 clear_bit(ASYI_TXBUSY, &portp->istate);
3516 }
3517 outb(srer, (ioaddr + EREG_DATA));
3518 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003519 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003521 stlen = min_t(unsigned int, len,
3522 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 outb((TDR + portp->uartaddr), ioaddr);
3524 outsb((ioaddr + EREG_DATA), tail, stlen);
3525 len -= stlen;
3526 tail += stlen;
3527 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3528 tail = portp->tx.buf;
3529 if (len > 0) {
3530 outsb((ioaddr + EREG_DATA), tail, len);
3531 tail += len;
3532 }
3533 portp->tx.tail = tail;
3534 }
3535
3536stl_txalldone:
3537 outb((EOSRR + portp->uartaddr), ioaddr);
3538 outb(0, (ioaddr + EREG_DATA));
3539}
3540
3541/*****************************************************************************/
3542
3543/*
3544 * Receive character interrupt handler. Determine if we have good chars
3545 * or bad chars and then process appropriately. Good chars are easy
3546 * just shove the lot into the RX buffer and set all status byte to 0.
3547 * If a bad RX char then process as required. This routine needs to be
3548 * fast! In practice it is possible that we get an interrupt on a port
3549 * that is closed. This can happen on hangups - since they completely
3550 * shutdown a port not in user context. Need to handle this case.
3551 */
3552
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003553static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003555 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 struct tty_struct *tty;
3557 unsigned int ioack, len, buflen;
3558 unsigned char status;
3559 char ch;
3560
Jiri Slabya0564e12006-12-08 02:38:37 -08003561 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
3563 ioack = inb(ioaddr + EREG_RXACK);
3564 if ((ioack & panelp->ackmask) != 0) {
3565 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3566 return;
3567 }
3568 portp = panelp->ports[(ioack >> 3)];
3569 tty = portp->tty;
3570
3571 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3572 outb((RDCR + portp->uartaddr), ioaddr);
3573 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003574 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003575 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 outb((RDSR + portp->uartaddr), ioaddr);
3577 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3578 portp->stats.rxlost += len;
3579 portp->stats.rxtotal += len;
3580 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003581 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003583 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003585 tty_prepare_flip_string(tty, &ptr, len);
3586 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 tty_schedule_flip(tty);
3588 portp->stats.rxtotal += len;
3589 }
3590 }
3591 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3592 outb((RDSR + portp->uartaddr), ioaddr);
3593 status = inb(ioaddr + EREG_DATA);
3594 ch = inb(ioaddr + EREG_DATA);
3595 if (status & ST_PARITY)
3596 portp->stats.rxparity++;
3597 if (status & ST_FRAMING)
3598 portp->stats.rxframing++;
3599 if (status & ST_OVERRUN)
3600 portp->stats.rxoverrun++;
3601 if (status & ST_BREAK)
3602 portp->stats.rxbreaks++;
3603 if (status & ST_SCHARMASK) {
3604 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3605 portp->stats.txxon++;
3606 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3607 portp->stats.txxoff++;
3608 goto stl_rxalldone;
3609 }
Alan Cox33f0f882006-01-09 20:54:13 -08003610 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 if (portp->rxmarkmsk & status) {
3612 if (status & ST_BREAK) {
3613 status = TTY_BREAK;
3614 if (portp->flags & ASYNC_SAK) {
3615 do_SAK(tty);
3616 BRDENABLE(portp->brdnr, portp->pagenr);
3617 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003618 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003620 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003622 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003624 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003626 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003628 tty_insert_flip_char(tty, ch, status);
3629 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 }
3631 } else {
3632 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3633 return;
3634 }
3635
3636stl_rxalldone:
3637 outb((EOSRR + portp->uartaddr), ioaddr);
3638 outb(0, (ioaddr + EREG_DATA));
3639}
3640
3641/*****************************************************************************/
3642
3643/*
3644 * Modem interrupt handler. The is called when the modem signal line
3645 * (DCD) has changed state. Leave most of the work to the off-level
3646 * processing routine.
3647 */
3648
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003649static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003651 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 unsigned int ioack;
3653 unsigned char misr;
3654
Jiri Slabya0564e12006-12-08 02:38:37 -08003655 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
3657 ioack = inb(ioaddr + EREG_MDACK);
3658 if (((ioack & panelp->ackmask) != 0) ||
3659 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3660 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3661 return;
3662 }
3663 portp = panelp->ports[(ioack >> 3)];
3664
3665 outb((MISR + portp->uartaddr), ioaddr);
3666 misr = inb(ioaddr + EREG_DATA);
3667 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003668 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 portp->stats.modem++;
3670 }
3671
3672 outb((EOSRR + portp->uartaddr), ioaddr);
3673 outb(0, (ioaddr + EREG_DATA));
3674}
3675
3676/*****************************************************************************/
3677/* SC26198 HARDWARE FUNCTIONS */
3678/*****************************************************************************/
3679
3680/*
3681 * These functions get/set/update the registers of the sc26198 UARTs.
3682 * Access to the sc26198 registers is via an address/data io port pair.
3683 * (Maybe should make this inline...)
3684 */
3685
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003686static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687{
3688 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003689 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690}
3691
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003692static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
3694 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3695 outb(value, (portp->ioaddr + XP_DATA));
3696}
3697
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003698static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
3700 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3701 if (inb(portp->ioaddr + XP_DATA) != value) {
3702 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003703 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003705 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706}
3707
3708/*****************************************************************************/
3709
3710/*
3711 * Functions to get and set the sc26198 global registers.
3712 */
3713
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003714static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715{
3716 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003717 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718}
3719
3720#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003721static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722{
3723 outb(regnr, (portp->ioaddr + XP_ADDR));
3724 outb(value, (portp->ioaddr + XP_DATA));
3725}
3726#endif
3727
3728/*****************************************************************************/
3729
3730/*
3731 * Inbitialize the UARTs in a panel. We don't care what sort of board
3732 * these ports are on - since the port io registers are almost
3733 * identical when dealing with ports.
3734 */
3735
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003736static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737{
3738 int chipmask, i;
3739 int nrchips, ioaddr;
3740
Jiri Slabya0564e12006-12-08 02:38:37 -08003741 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
3743 BRDENABLE(panelp->brdnr, panelp->pagenr);
3744
3745/*
3746 * Check that each chip is present and started up OK.
3747 */
3748 chipmask = 0;
3749 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3750 if (brdp->brdtype == BRD_ECHPCI)
3751 outb(panelp->pagenr, brdp->ioctrl);
3752
Jiri Slabyc62429d2006-12-08 02:39:14 -08003753 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754 ioaddr = panelp->iobase + (i * 4);
3755 outb(SCCR, (ioaddr + XP_ADDR));
3756 outb(CR_RESETALL, (ioaddr + XP_DATA));
3757 outb(TSTR, (ioaddr + XP_ADDR));
3758 if (inb(ioaddr + XP_DATA) != 0) {
3759 printk("STALLION: sc26198 not responding, "
3760 "brd=%d panel=%d chip=%d\n",
3761 panelp->brdnr, panelp->panelnr, i);
3762 continue;
3763 }
3764 chipmask |= (0x1 << i);
3765 outb(GCCR, (ioaddr + XP_ADDR));
3766 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3767 outb(WDTRCR, (ioaddr + XP_ADDR));
3768 outb(0xff, (ioaddr + XP_DATA));
3769 }
3770
3771 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003772 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773}
3774
3775/*****************************************************************************/
3776
3777/*
3778 * Initialize hardware specific port registers.
3779 */
3780
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003781static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782{
Jiri Slabya0564e12006-12-08 02:38:37 -08003783 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3784 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785
Jiri Slaby615e4a72006-12-08 02:38:38 -08003786 if ((brdp == NULL) || (panelp == NULL) ||
3787 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 return;
3789
3790 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3791 portp->uartaddr = (portp->portnr & 0x07) << 4;
3792 portp->pagenr = panelp->pagenr;
3793 portp->hwid = 0x1;
3794
3795 BRDENABLE(portp->brdnr, portp->pagenr);
3796 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3797 BRDDISABLE(portp->brdnr);
3798}
3799
3800/*****************************************************************************/
3801
3802/*
3803 * Set up the sc26198 registers for a port based on the termios port
3804 * settings.
3805 */
3806
Alan Cox606d0992006-12-08 02:38:45 -08003807static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003809 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 unsigned long flags;
3811 unsigned int baudrate;
3812 unsigned char mr0, mr1, mr2, clk;
3813 unsigned char imron, imroff, iopr, ipr;
3814
3815 mr0 = 0;
3816 mr1 = 0;
3817 mr2 = 0;
3818 clk = 0;
3819 iopr = 0;
3820 imron = 0;
3821 imroff = 0;
3822
3823 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003824 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825 return;
3826
3827/*
3828 * Set up the RX char ignore mask with those RX error types we
3829 * can ignore.
3830 */
3831 portp->rxignoremsk = 0;
3832 if (tiosp->c_iflag & IGNPAR)
3833 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3834 SR_RXOVERRUN);
3835 if (tiosp->c_iflag & IGNBRK)
3836 portp->rxignoremsk |= SR_RXBREAK;
3837
3838 portp->rxmarkmsk = SR_RXOVERRUN;
3839 if (tiosp->c_iflag & (INPCK | PARMRK))
3840 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3841 if (tiosp->c_iflag & BRKINT)
3842 portp->rxmarkmsk |= SR_RXBREAK;
3843
3844/*
3845 * Go through the char size, parity and stop bits and set all the
3846 * option register appropriately.
3847 */
3848 switch (tiosp->c_cflag & CSIZE) {
3849 case CS5:
3850 mr1 |= MR1_CS5;
3851 break;
3852 case CS6:
3853 mr1 |= MR1_CS6;
3854 break;
3855 case CS7:
3856 mr1 |= MR1_CS7;
3857 break;
3858 default:
3859 mr1 |= MR1_CS8;
3860 break;
3861 }
3862
3863 if (tiosp->c_cflag & CSTOPB)
3864 mr2 |= MR2_STOP2;
3865 else
3866 mr2 |= MR2_STOP1;
3867
3868 if (tiosp->c_cflag & PARENB) {
3869 if (tiosp->c_cflag & PARODD)
3870 mr1 |= (MR1_PARENB | MR1_PARODD);
3871 else
3872 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003873 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
3876 mr1 |= MR1_ERRBLOCK;
3877
3878/*
3879 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3880 * space for hardware flow control and the like. This should be set to
3881 * VMIN.
3882 */
3883 mr2 |= MR2_RXFIFOHALF;
3884
3885/*
3886 * Calculate the baud rate timers. For now we will just assume that
3887 * the input and output baud are the same. The sc26198 has a fixed
3888 * baud rate table, so only discrete baud rates possible.
3889 */
3890 baudrate = tiosp->c_cflag & CBAUD;
3891 if (baudrate & CBAUDEX) {
3892 baudrate &= ~CBAUDEX;
3893 if ((baudrate < 1) || (baudrate > 4))
3894 tiosp->c_cflag &= ~CBAUDEX;
3895 else
3896 baudrate += 15;
3897 }
3898 baudrate = stl_baudrates[baudrate];
3899 if ((tiosp->c_cflag & CBAUD) == B38400) {
3900 if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
3901 baudrate = 57600;
3902 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
3903 baudrate = 115200;
3904 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
3905 baudrate = 230400;
3906 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
3907 baudrate = 460800;
3908 else if ((portp->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
3909 baudrate = (portp->baud_base / portp->custom_divisor);
3910 }
3911 if (baudrate > STL_SC26198MAXBAUD)
3912 baudrate = STL_SC26198MAXBAUD;
3913
Jiri Slabyc62429d2006-12-08 02:39:14 -08003914 if (baudrate > 0)
3915 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 if (baudrate <= sc26198_baudtable[clk])
3917 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
3919/*
3920 * Check what form of modem signaling is required and set it up.
3921 */
3922 if (tiosp->c_cflag & CLOCAL) {
3923 portp->flags &= ~ASYNC_CHECK_CD;
3924 } else {
3925 iopr |= IOPR_DCDCOS;
3926 imron |= IR_IOPORT;
3927 portp->flags |= ASYNC_CHECK_CD;
3928 }
3929
3930/*
3931 * Setup sc26198 enhanced modes if we can. In particular we want to
3932 * handle as much of the flow control as possible automatically. As
3933 * well as saving a few CPU cycles it will also greatly improve flow
3934 * control reliability.
3935 */
3936 if (tiosp->c_iflag & IXON) {
3937 mr0 |= MR0_SWFTX | MR0_SWFT;
3938 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003939 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003941
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 if (tiosp->c_iflag & IXOFF)
3943 mr0 |= MR0_SWFRX;
3944
3945 if (tiosp->c_cflag & CRTSCTS) {
3946 mr2 |= MR2_AUTOCTS;
3947 mr1 |= MR1_AUTORTS;
3948 }
3949
3950/*
3951 * All sc26198 register values calculated so go through and set
3952 * them all up.
3953 */
3954
Jiri Slabya0564e12006-12-08 02:38:37 -08003955 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003957 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3958 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3959 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3961 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Alan Coxb65b5b52006-06-27 02:54:05 -07003963 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 BRDENABLE(portp->brdnr, portp->pagenr);
3965 stl_sc26198setreg(portp, IMR, 0);
3966 stl_sc26198updatereg(portp, MR0, mr0);
3967 stl_sc26198updatereg(portp, MR1, mr1);
3968 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3969 stl_sc26198updatereg(portp, MR2, mr2);
3970 stl_sc26198updatereg(portp, IOPIOR,
3971 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3972
3973 if (baudrate > 0) {
3974 stl_sc26198setreg(portp, TXCSR, clk);
3975 stl_sc26198setreg(portp, RXCSR, clk);
3976 }
3977
3978 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3979 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3980
3981 ipr = stl_sc26198getreg(portp, IPR);
3982 if (ipr & IPR_DCD)
3983 portp->sigs &= ~TIOCM_CD;
3984 else
3985 portp->sigs |= TIOCM_CD;
3986
3987 portp->imr = (portp->imr & ~imroff) | imron;
3988 stl_sc26198setreg(portp, IMR, portp->imr);
3989 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003990 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991}
3992
3993/*****************************************************************************/
3994
3995/*
3996 * Set the state of the DTR and RTS signals.
3997 */
3998
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003999static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000{
4001 unsigned char iopioron, iopioroff;
4002 unsigned long flags;
4003
Jiri Slabya0564e12006-12-08 02:38:37 -08004004 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
4005 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006
4007 iopioron = 0;
4008 iopioroff = 0;
4009 if (dtr == 0)
4010 iopioroff |= IPR_DTR;
4011 else if (dtr > 0)
4012 iopioron |= IPR_DTR;
4013 if (rts == 0)
4014 iopioroff |= IPR_RTS;
4015 else if (rts > 0)
4016 iopioron |= IPR_RTS;
4017
Alan Coxb65b5b52006-06-27 02:54:05 -07004018 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 BRDENABLE(portp->brdnr, portp->pagenr);
4020 stl_sc26198setreg(portp, IOPIOR,
4021 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
4022 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004023 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024}
4025
4026/*****************************************************************************/
4027
4028/*
4029 * Return the state of the signals.
4030 */
4031
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004032static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033{
4034 unsigned char ipr;
4035 unsigned long flags;
4036 int sigs;
4037
Jiri Slabya0564e12006-12-08 02:38:37 -08004038 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
Alan Coxb65b5b52006-06-27 02:54:05 -07004040 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 BRDENABLE(portp->brdnr, portp->pagenr);
4042 ipr = stl_sc26198getreg(portp, IPR);
4043 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004044 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
4046 sigs = 0;
4047 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
4048 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
4049 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
4050 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
4051 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01004052 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053}
4054
4055/*****************************************************************************/
4056
4057/*
4058 * Enable/Disable the Transmitter and/or Receiver.
4059 */
4060
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004061static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062{
4063 unsigned char ccr;
4064 unsigned long flags;
4065
Jiri Slabya0564e12006-12-08 02:38:37 -08004066 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
4068 ccr = portp->crenable;
4069 if (tx == 0)
4070 ccr &= ~CR_TXENABLE;
4071 else if (tx > 0)
4072 ccr |= CR_TXENABLE;
4073 if (rx == 0)
4074 ccr &= ~CR_RXENABLE;
4075 else if (rx > 0)
4076 ccr |= CR_RXENABLE;
4077
Alan Coxb65b5b52006-06-27 02:54:05 -07004078 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 BRDENABLE(portp->brdnr, portp->pagenr);
4080 stl_sc26198setreg(portp, SCCR, ccr);
4081 BRDDISABLE(portp->brdnr);
4082 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07004083 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084}
4085
4086/*****************************************************************************/
4087
4088/*
4089 * Start/stop the Transmitter and/or Receiver.
4090 */
4091
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004092static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093{
4094 unsigned char imr;
4095 unsigned long flags;
4096
Jiri Slabya0564e12006-12-08 02:38:37 -08004097 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
4099 imr = portp->imr;
4100 if (tx == 0)
4101 imr &= ~IR_TXRDY;
4102 else if (tx == 1)
4103 imr |= IR_TXRDY;
4104 if (rx == 0)
4105 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
4106 else if (rx > 0)
4107 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
4108
Alan Coxb65b5b52006-06-27 02:54:05 -07004109 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 BRDENABLE(portp->brdnr, portp->pagenr);
4111 stl_sc26198setreg(portp, IMR, imr);
4112 BRDDISABLE(portp->brdnr);
4113 portp->imr = imr;
4114 if (tx > 0)
4115 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07004116 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117}
4118
4119/*****************************************************************************/
4120
4121/*
4122 * Disable all interrupts from this port.
4123 */
4124
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004125static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126{
4127 unsigned long flags;
4128
Jiri Slabya0564e12006-12-08 02:38:37 -08004129 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Alan Coxb65b5b52006-06-27 02:54:05 -07004131 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 BRDENABLE(portp->brdnr, portp->pagenr);
4133 portp->imr = 0;
4134 stl_sc26198setreg(portp, IMR, 0);
4135 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004136 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137}
4138
4139/*****************************************************************************/
4140
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004141static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142{
4143 unsigned long flags;
4144
Jiri Slabya0564e12006-12-08 02:38:37 -08004145 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Alan Coxb65b5b52006-06-27 02:54:05 -07004147 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 BRDENABLE(portp->brdnr, portp->pagenr);
4149 if (len == 1) {
4150 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4151 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004152 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004154
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004156 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157}
4158
4159/*****************************************************************************/
4160
4161/*
4162 * Take flow control actions...
4163 */
4164
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004165static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166{
4167 struct tty_struct *tty;
4168 unsigned long flags;
4169 unsigned char mr0;
4170
Jiri Slabya0564e12006-12-08 02:38:37 -08004171 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Jiri Slaby615e4a72006-12-08 02:38:38 -08004173 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 return;
4175 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004176 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 return;
4178
Alan Coxb65b5b52006-06-27 02:54:05 -07004179 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 BRDENABLE(portp->brdnr, portp->pagenr);
4181
4182 if (state) {
4183 if (tty->termios->c_iflag & IXOFF) {
4184 mr0 = stl_sc26198getreg(portp, MR0);
4185 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4186 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4187 mr0 |= MR0_SWFRX;
4188 portp->stats.rxxon++;
4189 stl_sc26198wait(portp);
4190 stl_sc26198setreg(portp, MR0, mr0);
4191 }
4192/*
4193 * Question: should we return RTS to what it was before? It may
4194 * have been set by an ioctl... Suppose not, since if you have
4195 * hardware flow control set then it is pretty silly to go and
4196 * set the RTS line by hand.
4197 */
4198 if (tty->termios->c_cflag & CRTSCTS) {
4199 stl_sc26198setreg(portp, MR1,
4200 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4201 stl_sc26198setreg(portp, IOPIOR,
4202 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4203 portp->stats.rxrtson++;
4204 }
4205 } else {
4206 if (tty->termios->c_iflag & IXOFF) {
4207 mr0 = stl_sc26198getreg(portp, MR0);
4208 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4209 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4210 mr0 &= ~MR0_SWFRX;
4211 portp->stats.rxxoff++;
4212 stl_sc26198wait(portp);
4213 stl_sc26198setreg(portp, MR0, mr0);
4214 }
4215 if (tty->termios->c_cflag & CRTSCTS) {
4216 stl_sc26198setreg(portp, MR1,
4217 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4218 stl_sc26198setreg(portp, IOPIOR,
4219 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4220 portp->stats.rxrtsoff++;
4221 }
4222 }
4223
4224 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004225 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226}
4227
4228/*****************************************************************************/
4229
4230/*
4231 * Send a flow control character.
4232 */
4233
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004234static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235{
4236 struct tty_struct *tty;
4237 unsigned long flags;
4238 unsigned char mr0;
4239
Jiri Slabya0564e12006-12-08 02:38:37 -08004240 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Jiri Slaby615e4a72006-12-08 02:38:38 -08004242 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 return;
4244 tty = portp->tty;
Jiri Slaby615e4a72006-12-08 02:38:38 -08004245 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 return;
4247
Alan Coxb65b5b52006-06-27 02:54:05 -07004248 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249 BRDENABLE(portp->brdnr, portp->pagenr);
4250 if (state) {
4251 mr0 = stl_sc26198getreg(portp, MR0);
4252 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4253 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4254 mr0 |= MR0_SWFRX;
4255 portp->stats.rxxon++;
4256 stl_sc26198wait(portp);
4257 stl_sc26198setreg(portp, MR0, mr0);
4258 } else {
4259 mr0 = stl_sc26198getreg(portp, MR0);
4260 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4261 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4262 mr0 &= ~MR0_SWFRX;
4263 portp->stats.rxxoff++;
4264 stl_sc26198wait(portp);
4265 stl_sc26198setreg(portp, MR0, mr0);
4266 }
4267 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004268 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271/*****************************************************************************/
4272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004273static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274{
4275 unsigned long flags;
4276
Jiri Slabya0564e12006-12-08 02:38:37 -08004277 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
Jiri Slaby615e4a72006-12-08 02:38:38 -08004279 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 return;
4281
Alan Coxb65b5b52006-06-27 02:54:05 -07004282 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 BRDENABLE(portp->brdnr, portp->pagenr);
4284 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4285 stl_sc26198setreg(portp, SCCR, portp->crenable);
4286 BRDDISABLE(portp->brdnr);
4287 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004288 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289}
4290
4291/*****************************************************************************/
4292
4293/*
4294 * Return the current state of data flow on this port. This is only
4295 * really interresting when determining if data has fully completed
4296 * transmission or not... The sc26198 interrupt scheme cannot
4297 * determine when all data has actually drained, so we need to
4298 * check the port statusy register to be sure.
4299 */
4300
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004301static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004302{
4303 unsigned long flags;
4304 unsigned char sr;
4305
Jiri Slabya0564e12006-12-08 02:38:37 -08004306 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Jiri Slaby615e4a72006-12-08 02:38:38 -08004308 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004309 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004311 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
Alan Coxb65b5b52006-06-27 02:54:05 -07004313 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314 BRDENABLE(portp->brdnr, portp->pagenr);
4315 sr = stl_sc26198getreg(portp, SR);
4316 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004317 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Jesper Juhl014c2542006-01-15 02:37:08 +01004319 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320}
4321
4322/*****************************************************************************/
4323
4324/*
4325 * Delay for a small amount of time, to give the sc26198 a chance
4326 * to process a command...
4327 */
4328
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004329static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330{
4331 int i;
4332
Jiri Slabya0564e12006-12-08 02:38:37 -08004333 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334
Jiri Slaby615e4a72006-12-08 02:38:38 -08004335 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 return;
4337
Jiri Slabyc62429d2006-12-08 02:39:14 -08004338 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 stl_sc26198getglobreg(portp, TSTR);
4340}
4341
4342/*****************************************************************************/
4343
4344/*
4345 * If we are TX flow controlled and in IXANY mode then we may
4346 * need to unflow control here. We gotta do this because of the
4347 * automatic flow control modes of the sc26198.
4348 */
4349
Jiri Slaby60be4812006-12-08 02:38:40 -08004350static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351{
4352 unsigned char mr0;
4353
4354 mr0 = stl_sc26198getreg(portp, MR0);
4355 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4356 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4357 stl_sc26198wait(portp);
4358 stl_sc26198setreg(portp, MR0, mr0);
4359 clear_bit(ASYI_TXFLOWED, &portp->istate);
4360}
4361
4362/*****************************************************************************/
4363
4364/*
4365 * Interrupt service routine for sc26198 panels.
4366 */
4367
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004368static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004370 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 unsigned int iack;
4372
Alan Coxb65b5b52006-06-27 02:54:05 -07004373 spin_lock(&brd_lock);
4374
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375/*
4376 * Work around bug in sc26198 chip... Cannot have A6 address
4377 * line of UART high, else iack will be returned as 0.
4378 */
4379 outb(0, (iobase + 1));
4380
4381 iack = inb(iobase + XP_IACK);
4382 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4383
4384 if (iack & IVR_RXDATA)
4385 stl_sc26198rxisr(portp, iack);
4386 else if (iack & IVR_TXDATA)
4387 stl_sc26198txisr(portp);
4388 else
4389 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004390
4391 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392}
4393
4394/*****************************************************************************/
4395
4396/*
4397 * Transmit interrupt handler. This has gotta be fast! Handling TX
4398 * chars is pretty simple, stuff as many as possible from the TX buffer
4399 * into the sc26198 FIFO.
4400 * In practice it is possible that interrupts are enabled but that the
4401 * port has been hung up. Need to handle not having any TX buffer here,
4402 * this is done by using the side effect that head and tail will also
4403 * be NULL if the buffer has been freed.
4404 */
4405
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004406static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407{
4408 unsigned int ioaddr;
4409 unsigned char mr0;
4410 int len, stlen;
4411 char *head, *tail;
4412
Jiri Slabya0564e12006-12-08 02:38:37 -08004413 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
4415 ioaddr = portp->ioaddr;
4416 head = portp->tx.head;
4417 tail = portp->tx.tail;
4418 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4419 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4420 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4421 set_bit(ASYI_TXLOW, &portp->istate);
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004422 if (portp->tty)
4423 tty_wakeup(portp->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424 }
4425
4426 if (len == 0) {
4427 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4428 mr0 = inb(ioaddr + XP_DATA);
4429 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4430 portp->imr &= ~IR_TXRDY;
4431 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4432 outb(portp->imr, (ioaddr + XP_DATA));
4433 clear_bit(ASYI_TXBUSY, &portp->istate);
4434 } else {
4435 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4436 outb(mr0, (ioaddr + XP_DATA));
4437 }
4438 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004439 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004441 stlen = min_t(unsigned int, len,
4442 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 outb(GTXFIFO, (ioaddr + XP_ADDR));
4444 outsb((ioaddr + XP_DATA), tail, stlen);
4445 len -= stlen;
4446 tail += stlen;
4447 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4448 tail = portp->tx.buf;
4449 if (len > 0) {
4450 outsb((ioaddr + XP_DATA), tail, len);
4451 tail += len;
4452 }
4453 portp->tx.tail = tail;
4454 }
4455}
4456
4457/*****************************************************************************/
4458
4459/*
4460 * Receive character interrupt handler. Determine if we have good chars
4461 * or bad chars and then process appropriately. Good chars are easy
4462 * just shove the lot into the RX buffer and set all status byte to 0.
4463 * If a bad RX char then process as required. This routine needs to be
4464 * fast! In practice it is possible that we get an interrupt on a port
4465 * that is closed. This can happen on hangups - since they completely
4466 * shutdown a port not in user context. Need to handle this case.
4467 */
4468
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004469static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470{
4471 struct tty_struct *tty;
4472 unsigned int len, buflen, ioaddr;
4473
Jiri Slabya0564e12006-12-08 02:38:37 -08004474 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
4476 tty = portp->tty;
4477 ioaddr = portp->ioaddr;
4478 outb(GIBCR, (ioaddr + XP_ADDR));
4479 len = inb(ioaddr + XP_DATA) + 1;
4480
4481 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004482 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004483 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484 outb(GRXFIFO, (ioaddr + XP_ADDR));
4485 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4486 portp->stats.rxlost += len;
4487 portp->stats.rxtotal += len;
4488 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004489 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004491 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004493 tty_prepare_flip_string(tty, &ptr, len);
4494 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 tty_schedule_flip(tty);
4496 portp->stats.rxtotal += len;
4497 }
4498 }
4499 } else {
4500 stl_sc26198rxbadchars(portp);
4501 }
4502
4503/*
4504 * If we are TX flow controlled and in IXANY mode then we may need
4505 * to unflow control here. We gotta do this because of the automatic
4506 * flow control modes of the sc26198.
4507 */
4508 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004509 if ((tty != NULL) &&
4510 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511 (tty->termios->c_iflag & IXANY)) {
4512 stl_sc26198txunflow(portp, tty);
4513 }
4514 }
4515}
4516
4517/*****************************************************************************/
4518
4519/*
4520 * Process an RX bad character.
4521 */
4522
Jiri Slaby60be4812006-12-08 02:38:40 -08004523static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524{
4525 struct tty_struct *tty;
4526 unsigned int ioaddr;
4527
4528 tty = portp->tty;
4529 ioaddr = portp->ioaddr;
4530
4531 if (status & SR_RXPARITY)
4532 portp->stats.rxparity++;
4533 if (status & SR_RXFRAMING)
4534 portp->stats.rxframing++;
4535 if (status & SR_RXOVERRUN)
4536 portp->stats.rxoverrun++;
4537 if (status & SR_RXBREAK)
4538 portp->stats.rxbreaks++;
4539
Jiri Slaby615e4a72006-12-08 02:38:38 -08004540 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 ((portp->rxignoremsk & status) == 0)) {
4542 if (portp->rxmarkmsk & status) {
4543 if (status & SR_RXBREAK) {
4544 status = TTY_BREAK;
4545 if (portp->flags & ASYNC_SAK) {
4546 do_SAK(tty);
4547 BRDENABLE(portp->brdnr, portp->pagenr);
4548 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004549 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004551 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004553 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004555 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004557 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559
Alan Cox33f0f882006-01-09 20:54:13 -08004560 tty_insert_flip_char(tty, ch, status);
4561 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562
4563 if (status == 0)
4564 portp->stats.rxtotal++;
4565 }
4566}
4567
4568/*****************************************************************************/
4569
4570/*
4571 * Process all characters in the RX FIFO of the UART. Check all char
4572 * status bytes as well, and process as required. We need to check
4573 * all bytes in the FIFO, in case some more enter the FIFO while we
4574 * are here. To get the exact character error type we need to switch
4575 * into CHAR error mode (that is why we need to make sure we empty
4576 * the FIFO).
4577 */
4578
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004579static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580{
4581 unsigned char status, mr1;
4582 char ch;
4583
4584/*
4585 * To get the precise error type for each character we must switch
4586 * back into CHAR error mode.
4587 */
4588 mr1 = stl_sc26198getreg(portp, MR1);
4589 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4590
4591 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4592 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4593 ch = stl_sc26198getreg(portp, RXFIFO);
4594 stl_sc26198rxbadch(portp, status, ch);
4595 }
4596
4597/*
4598 * To get correct interrupt class we must switch back into BLOCK
4599 * error mode.
4600 */
4601 stl_sc26198setreg(portp, MR1, mr1);
4602}
4603
4604/*****************************************************************************/
4605
4606/*
4607 * Other interrupt handler. This includes modem signals, flow
4608 * control actions, etc. Most stuff is left to off-level interrupt
4609 * processing time.
4610 */
4611
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004612static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004613{
4614 unsigned char cir, ipr, xisr;
4615
Jiri Slabya0564e12006-12-08 02:38:37 -08004616 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617
4618 cir = stl_sc26198getglobreg(portp, CIR);
4619
4620 switch (cir & CIR_SUBTYPEMASK) {
4621 case CIR_SUBCOS:
4622 ipr = stl_sc26198getreg(portp, IPR);
4623 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004624 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625 portp->stats.modem++;
4626 }
4627 break;
4628 case CIR_SUBXONXOFF:
4629 xisr = stl_sc26198getreg(portp, XISR);
4630 if (xisr & XISR_RXXONGOT) {
4631 set_bit(ASYI_TXFLOWED, &portp->istate);
4632 portp->stats.txxoff++;
4633 }
4634 if (xisr & XISR_RXXOFFGOT) {
4635 clear_bit(ASYI_TXFLOWED, &portp->istate);
4636 portp->stats.txxon++;
4637 }
4638 break;
4639 case CIR_SUBBREAK:
4640 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4641 stl_sc26198rxbadchars(portp);
4642 break;
4643 default:
4644 break;
4645 }
4646}
4647
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004648static void stl_free_isabrds(void)
4649{
4650 struct stlbrd *brdp;
4651 unsigned int i;
4652
4653 for (i = 0; i < stl_nrbrds; i++) {
4654 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4655 continue;
4656
4657 free_irq(brdp->irq, brdp);
4658
4659 stl_cleanup_panels(brdp);
4660
4661 release_region(brdp->ioaddr1, brdp->iosize1);
4662 if (brdp->iosize2 > 0)
4663 release_region(brdp->ioaddr2, brdp->iosize2);
4664
4665 kfree(brdp);
4666 stl_brds[i] = NULL;
4667 }
4668}
4669
Jiri Slaby23b85a12006-12-08 02:38:40 -08004670/*
4671 * Loadable module initialization stuff.
4672 */
4673static int __init stallion_module_init(void)
4674{
Jiri Slaby843b5682006-12-08 02:39:12 -08004675 struct stlbrd *brdp;
4676 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004677 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004678 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004679
4680 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4681
4682 spin_lock_init(&stallion_lock);
4683 spin_lock_init(&brd_lock);
4684
Jiri Slabye4151092007-06-08 13:46:52 -07004685 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4686 if (!stl_serial) {
4687 retval = -ENOMEM;
4688 goto err;
4689 }
4690
4691 stl_serial->owner = THIS_MODULE;
4692 stl_serial->driver_name = stl_drvname;
4693 stl_serial->name = "ttyE";
4694 stl_serial->major = STL_SERIALMAJOR;
4695 stl_serial->minor_start = 0;
4696 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4697 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4698 stl_serial->init_termios = stl_deftermios;
4699 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4700 tty_set_operations(stl_serial, &stl_ops);
4701
4702 retval = tty_register_driver(stl_serial);
4703 if (retval) {
4704 printk("STALLION: failed to register serial driver\n");
4705 goto err_frtty;
4706 }
4707
Jiri Slaby843b5682006-12-08 02:39:12 -08004708/*
4709 * Find any dynamically supported boards. That is via module load
4710 * line options.
4711 */
4712 for (i = stl_nrbrds; i < stl_nargs; i++) {
4713 memset(&conf, 0, sizeof(conf));
4714 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4715 continue;
4716 if ((brdp = stl_allocbrd()) == NULL)
4717 continue;
4718 brdp->brdnr = i;
4719 brdp->brdtype = conf.brdtype;
4720 brdp->ioaddr1 = conf.ioaddr1;
4721 brdp->ioaddr2 = conf.ioaddr2;
4722 brdp->irq = conf.irq;
4723 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004724 stl_brds[brdp->brdnr] = brdp;
4725 if (stl_brdinit(brdp)) {
4726 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004727 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004728 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004729 for (j = 0; j < brdp->nrports; j++)
4730 tty_register_device(stl_serial,
4731 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004732 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004733 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004734 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004735
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004736 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004737 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004738 if (retval && stl_nrbrds == 0) {
4739 printk(KERN_ERR "STALLION: can't register pci driver\n");
4740 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004741 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004742
4743/*
4744 * Set up a character driver for per board stuff. This is mainly used
4745 * to do stats ioctls on the ports.
4746 */
4747 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4748 printk("STALLION: failed to register serial board device\n");
4749
4750 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004751 if (IS_ERR(stallion_class))
4752 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004753 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004754 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4755 "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004756
Jiri Slaby23b85a12006-12-08 02:38:40 -08004757 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004758err_unrtty:
4759 tty_unregister_driver(stl_serial);
4760err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004761 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004762err:
4763 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004764}
4765
4766static void __exit stallion_module_exit(void)
4767{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004768 struct stlbrd *brdp;
4769 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004770
4771 pr_debug("cleanup_module()\n");
4772
4773 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4774 stl_drvversion);
4775
4776/*
4777 * Free up all allocated resources used by the ports. This includes
4778 * memory and interrupts. As part of this process we will also do
4779 * a hangup on every open port - to try to flush out any processes
4780 * hanging onto ports.
4781 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004782 for (i = 0; i < stl_nrbrds; i++) {
4783 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4784 continue;
4785 for (j = 0; j < brdp->nrports; j++)
4786 tty_unregister_device(stl_serial,
4787 brdp->brdnr * STL_MAXPORTS + j);
4788 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004789
Jiri Slaby23b85a12006-12-08 02:38:40 -08004790 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004791 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004792 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004793 class_destroy(stallion_class);
4794
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004795 pci_unregister_driver(&stl_pcidriver);
4796
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004797 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004798
4799 tty_unregister_driver(stl_serial);
4800 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004801}
4802
4803module_init(stallion_module_init);
4804module_exit(stallion_module_exit);
4805
4806MODULE_AUTHOR("Greg Ungerer");
4807MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4808MODULE_LICENSE("GPL");