blob: b4ba5edea33d67a94477e16f482745587c3183fa [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>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040030#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/slab.h>
32#include <linux/interrupt.h>
33#include <linux/tty.h>
34#include <linux/tty_flip.h>
35#include <linux/serial.h>
Alexey Dobriyan8561c442009-03-31 15:19:18 -070036#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/cd1400.h>
38#include <linux/sc26198.h>
39#include <linux/comstats.h>
40#include <linux/stallion.h>
41#include <linux/ioport.h>
42#include <linux/init.h>
43#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/device.h>
45#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080046#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48#include <asm/io.h>
49#include <asm/uaccess.h>
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
53/*****************************************************************************/
54
55/*
56 * Define different board types. Use the standard Stallion "assigned"
57 * board numbers. Boards supported in this driver are abbreviated as
58 * EIO = EasyIO and ECH = EasyConnection 8/32.
59 */
60#define BRD_EASYIO 20
61#define BRD_ECH 21
62#define BRD_ECHMC 22
63#define BRD_ECHPCI 26
64#define BRD_ECH64PCI 27
65#define BRD_EASYIOPCI 28
66
Jiri Slaby843b5682006-12-08 02:39:12 -080067struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080068 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 int ioaddr1;
70 int ioaddr2;
71 unsigned long memaddr;
72 int irq;
73 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
Jiri Slaby843b5682006-12-08 02:39:12 -080076static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78/*****************************************************************************/
79
80/*
81 * Define some important driver characteristics. Device major numbers
82 * allocated as per Linux Device Registry.
83 */
84#ifndef STL_SIOMEMMAJOR
85#define STL_SIOMEMMAJOR 28
86#endif
87#ifndef STL_SERIALMAJOR
88#define STL_SERIALMAJOR 24
89#endif
90#ifndef STL_CALLOUTMAJOR
91#define STL_CALLOUTMAJOR 25
92#endif
93
94/*
95 * Set the TX buffer size. Bigger is better, but we don't want
96 * to chew too much memory with buffers!
97 */
98#define STL_TXBUFLOW 512
99#define STL_TXBUFSIZE 4096
100
101/*****************************************************************************/
102
103/*
104 * Define our local driver identity first. Set up stuff to deal with
105 * all the local structures required by a serial tty driver.
106 */
107static char *stl_drvtitle = "Stallion Multiport Serial Driver";
108static char *stl_drvname = "stallion";
109static char *stl_drvversion = "5.6.0";
110
111static struct tty_driver *stl_serial;
112
113/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 * Define a local default termios struct. All ports will be created
115 * with this termios initially. Basically all it defines is a raw port
116 * at 9600, 8 data bits, 1 stop bit.
117 */
Alan Cox606d0992006-12-08 02:38:45 -0800118static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
120 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800121 .c_ispeed = 9600,
122 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123};
124
125/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 * Define global place to put buffer overflow characters.
127 */
128static char stl_unwanted[SC26198_RXFIFOSIZE];
129
130/*****************************************************************************/
131
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800132static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800133static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Alan Cox31f35932009-01-02 13:45:05 +0000135static const struct tty_port_operations stl_port_ops;
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/*
138 * Per board state flags. Used with the state field of the board struct.
139 * Not really much here!
140 */
141#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800142#define STL_PROBED 0x2
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145/*
146 * Define the port structure istate flags. These set of flags are
147 * modified at interrupt time - so setting and reseting them needs
148 * to be atomic. Use the bit clear/setting routines for this.
149 */
150#define ASYI_TXBUSY 1
151#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800152#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154/*
155 * Define an array of board names as printable strings. Handy for
156 * referencing boards when printing trace and stuff.
157 */
158static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800159 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,
175 NULL,
176 NULL,
177 NULL,
178 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 "EasyIO",
180 "EC8/32-AT",
181 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800182 NULL,
183 NULL,
184 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "EC8/32-PCI",
186 "EC8/64-PCI",
187 "EasyIO-PCI",
188};
189
190/*****************************************************************************/
191
192/*
193 * Define some string labels for arguments passed from the module
194 * load line. These allow for easy board definitions, and easy
195 * modification of the io, memory and irq resoucres.
196 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800197static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198static char *board0[4];
199static char *board1[4];
200static char *board2[4];
201static char *board3[4];
202
203static char **stl_brdsp[] = {
204 (char **) &board0,
205 (char **) &board1,
206 (char **) &board2,
207 (char **) &board3
208};
209
210/*
211 * Define a set of common board names, and types. This is used to
212 * parse any module arguments.
213 */
214
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800215static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 char *name;
217 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800218} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 { "easyio", BRD_EASYIO },
220 { "eio", BRD_EASYIO },
221 { "20", BRD_EASYIO },
222 { "ec8/32", BRD_ECH },
223 { "ec8/32-at", BRD_ECH },
224 { "ec8/32-isa", BRD_ECH },
225 { "ech", BRD_ECH },
226 { "echat", BRD_ECH },
227 { "21", BRD_ECH },
228 { "ec8/32-mc", BRD_ECHMC },
229 { "ec8/32-mca", BRD_ECHMC },
230 { "echmc", BRD_ECHMC },
231 { "echmca", BRD_ECHMC },
232 { "22", BRD_ECHMC },
233 { "ec8/32-pc", BRD_ECHPCI },
234 { "ec8/32-pci", BRD_ECHPCI },
235 { "26", BRD_ECHPCI },
236 { "ec8/64-pc", BRD_ECH64PCI },
237 { "ec8/64-pci", BRD_ECH64PCI },
238 { "ech-pci", BRD_ECH64PCI },
239 { "echpci", BRD_ECH64PCI },
240 { "echpc", BRD_ECH64PCI },
241 { "27", BRD_ECH64PCI },
242 { "easyio-pc", BRD_EASYIOPCI },
243 { "easyio-pci", BRD_EASYIOPCI },
244 { "eio-pci", BRD_EASYIOPCI },
245 { "eiopci", BRD_EASYIOPCI },
246 { "28", BRD_EASYIOPCI },
247};
248
249/*
250 * Define the module agruments.
251 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253module_param_array(board0, charp, &stl_nargs, 0);
254MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
255module_param_array(board1, charp, &stl_nargs, 0);
256MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
257module_param_array(board2, charp, &stl_nargs, 0);
258MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
259module_param_array(board3, charp, &stl_nargs, 0);
260MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
261
262/*****************************************************************************/
263
264/*
265 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
266 * to the directly accessible io ports of these boards (not the uarts -
267 * they are in cd1400.h and sc26198.h).
268 */
269#define EIO_8PORTRS 0x04
270#define EIO_4PORTRS 0x05
271#define EIO_8PORTDI 0x00
272#define EIO_8PORTM 0x06
273#define EIO_MK3 0x03
274#define EIO_IDBITMASK 0x07
275
276#define EIO_BRDMASK 0xf0
277#define ID_BRD4 0x10
278#define ID_BRD8 0x20
279#define ID_BRD16 0x30
280
281#define EIO_INTRPEND 0x08
282#define EIO_INTEDGE 0x00
283#define EIO_INTLEVEL 0x08
284#define EIO_0WS 0x10
285
286#define ECH_ID 0xa0
287#define ECH_IDBITMASK 0xe0
288#define ECH_BRDENABLE 0x08
289#define ECH_BRDDISABLE 0x00
290#define ECH_INTENABLE 0x01
291#define ECH_INTDISABLE 0x00
292#define ECH_INTLEVEL 0x02
293#define ECH_INTEDGE 0x00
294#define ECH_INTRPEND 0x01
295#define ECH_BRDRESET 0x01
296
297#define ECHMC_INTENABLE 0x01
298#define ECHMC_BRDRESET 0x02
299
300#define ECH_PNLSTATUS 2
301#define ECH_PNL16PORT 0x20
302#define ECH_PNLIDMASK 0x07
303#define ECH_PNLXPID 0x40
304#define ECH_PNLINTRPEND 0x80
305
306#define ECH_ADDR2MASK 0x1e0
307
308/*
309 * Define the vector mapping bits for the programmable interrupt board
310 * hardware. These bits encode the interrupt for the board to use - it
311 * is software selectable (except the EIO-8M).
312 */
313static unsigned char stl_vecmap[] = {
314 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
315 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
316};
317
318/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700319 * Lock ordering is that you may not take stallion_lock holding
320 * brd_lock.
321 */
322
323static spinlock_t brd_lock; /* Guard the board mapping */
324static spinlock_t stallion_lock; /* Guard the tty driver */
325
326/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 * Set up enable and disable macros for the ECH boards. They require
328 * the secondary io address space to be activated and deactivated.
329 * This way all ECH boards can share their secondary io region.
330 * If this is an ECH-PCI board then also need to set the page pointer
331 * to point to the correct page.
332 */
333#define BRDENABLE(brdnr,pagenr) \
334 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
335 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
336 stl_brds[(brdnr)]->ioctrl); \
337 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
338 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
339
340#define BRDDISABLE(brdnr) \
341 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
342 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
343 stl_brds[(brdnr)]->ioctrl);
344
345#define STL_CD1400MAXBAUD 230400
346#define STL_SC26198MAXBAUD 460800
347
348#define STL_BAUDBASE 115200
349#define STL_CLOSEDELAY (5 * HZ / 10)
350
351/*****************************************************************************/
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353/*
354 * Define the Stallion PCI vendor and device IDs.
355 */
356#ifndef PCI_VENDOR_ID_STALLION
357#define PCI_VENDOR_ID_STALLION 0x124d
358#endif
359#ifndef PCI_DEVICE_ID_ECHPCI832
360#define PCI_DEVICE_ID_ECHPCI832 0x0000
361#endif
362#ifndef PCI_DEVICE_ID_ECHPCI864
363#define PCI_DEVICE_ID_ECHPCI864 0x0002
364#endif
365#ifndef PCI_DEVICE_ID_EIOPCI
366#define PCI_DEVICE_ID_EIOPCI 0x0003
367#endif
368
369/*
370 * Define structure to hold all Stallion PCI boards.
371 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800373static struct pci_device_id stl_pcibrds[] = {
374 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
375 .driver_data = BRD_ECH64PCI },
376 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
377 .driver_data = BRD_EASYIOPCI },
378 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
379 .driver_data = BRD_ECHPCI },
380 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
381 .driver_data = BRD_ECHPCI },
382 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800384MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
386/*****************************************************************************/
387
388/*
389 * Define macros to extract a brd/port number from a minor number.
390 */
391#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
392#define MINOR2PORT(min) ((min) & 0x3f)
393
394/*
395 * Define a baud rate table that converts termios baud rate selector
396 * into the actual baud rate value. All baud rate calculations are
397 * based on the actual baud rate required.
398 */
399static unsigned int stl_baudrates[] = {
400 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
401 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
402};
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404/*****************************************************************************/
405
406/*
407 * Declare all those functions in this driver!
408 */
409
Alan Cox894cb912009-10-13 16:34:15 +0100410static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800411static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100412static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800413static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415/*
416 * CD1400 uart specific handling functions.
417 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800418static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
419static int stl_cd1400getreg(struct stlport *portp, int regnr);
420static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
421static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
422static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800423static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800424static int stl_cd1400getsignals(struct stlport *portp);
425static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
426static void stl_cd1400ccrwait(struct stlport *portp);
427static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
428static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
429static void stl_cd1400disableintrs(struct stlport *portp);
430static void stl_cd1400sendbreak(struct stlport *portp, int len);
431static void stl_cd1400flowctrl(struct stlport *portp, int state);
432static void stl_cd1400sendflow(struct stlport *portp, int state);
433static void stl_cd1400flush(struct stlport *portp);
434static int stl_cd1400datastate(struct stlport *portp);
435static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
436static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
437static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
438static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
439static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800441static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443/*
444 * SC26198 uart specific handling functions.
445 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800446static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
447static int stl_sc26198getreg(struct stlport *portp, int regnr);
448static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
449static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
450static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
451static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800452static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800453static int stl_sc26198getsignals(struct stlport *portp);
454static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
455static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
456static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
457static void stl_sc26198disableintrs(struct stlport *portp);
458static void stl_sc26198sendbreak(struct stlport *portp, int len);
459static void stl_sc26198flowctrl(struct stlport *portp, int state);
460static void stl_sc26198sendflow(struct stlport *portp, int state);
461static void stl_sc26198flush(struct stlport *portp);
462static int stl_sc26198datastate(struct stlport *portp);
463static void stl_sc26198wait(struct stlport *portp);
464static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
465static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
466static void stl_sc26198txisr(struct stlport *port);
467static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
468static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
469static void stl_sc26198rxbadchars(struct stlport *portp);
470static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472/*****************************************************************************/
473
474/*
475 * Generic UART support structure.
476 */
477typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800478 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
479 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800480 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800481 int (*getsignals)(struct stlport *portp);
482 void (*setsignals)(struct stlport *portp, int dtr, int rts);
483 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
484 void (*startrxtx)(struct stlport *portp, int rx, int tx);
485 void (*disableintrs)(struct stlport *portp);
486 void (*sendbreak)(struct stlport *portp, int len);
487 void (*flowctrl)(struct stlport *portp, int state);
488 void (*sendflow)(struct stlport *portp, int state);
489 void (*flush)(struct stlport *portp);
490 int (*datastate)(struct stlport *portp);
491 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492} uart_t;
493
494/*
495 * Define some macros to make calling these functions nice and clean.
496 */
497#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
498#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
499#define stl_setport (* ((uart_t *) portp->uartp)->setport)
500#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
501#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
502#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
503#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
504#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
505#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
506#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
507#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
508#define stl_flush (* ((uart_t *) portp->uartp)->flush)
509#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
510
511/*****************************************************************************/
512
513/*
514 * CD1400 UART specific data initialization.
515 */
516static uart_t stl_cd1400uart = {
517 stl_cd1400panelinit,
518 stl_cd1400portinit,
519 stl_cd1400setport,
520 stl_cd1400getsignals,
521 stl_cd1400setsignals,
522 stl_cd1400enablerxtx,
523 stl_cd1400startrxtx,
524 stl_cd1400disableintrs,
525 stl_cd1400sendbreak,
526 stl_cd1400flowctrl,
527 stl_cd1400sendflow,
528 stl_cd1400flush,
529 stl_cd1400datastate,
530 stl_cd1400eiointr
531};
532
533/*
534 * Define the offsets within the register bank of a cd1400 based panel.
535 * These io address offsets are common to the EasyIO board as well.
536 */
537#define EREG_ADDR 0
538#define EREG_DATA 4
539#define EREG_RXACK 5
540#define EREG_TXACK 6
541#define EREG_MDACK 7
542
543#define EREG_BANKSIZE 8
544
545#define CD1400_CLK 25000000
546#define CD1400_CLK8M 20000000
547
548/*
549 * Define the cd1400 baud rate clocks. These are used when calculating
550 * what clock and divisor to use for the required baud rate. Also
551 * define the maximum baud rate allowed, and the default base baud.
552 */
553static int stl_cd1400clkdivs[] = {
554 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
555};
556
557/*****************************************************************************/
558
559/*
560 * SC26198 UART specific data initization.
561 */
562static uart_t stl_sc26198uart = {
563 stl_sc26198panelinit,
564 stl_sc26198portinit,
565 stl_sc26198setport,
566 stl_sc26198getsignals,
567 stl_sc26198setsignals,
568 stl_sc26198enablerxtx,
569 stl_sc26198startrxtx,
570 stl_sc26198disableintrs,
571 stl_sc26198sendbreak,
572 stl_sc26198flowctrl,
573 stl_sc26198sendflow,
574 stl_sc26198flush,
575 stl_sc26198datastate,
576 stl_sc26198intr
577};
578
579/*
580 * Define the offsets within the register bank of a sc26198 based panel.
581 */
582#define XP_DATA 0
583#define XP_ADDR 1
584#define XP_MODID 2
585#define XP_STATUS 2
586#define XP_IACK 3
587
588#define XP_BANKSIZE 4
589
590/*
591 * Define the sc26198 baud rate table. Offsets within the table
592 * represent the actual baud rate selector of sc26198 registers.
593 */
594static unsigned int sc26198_baudtable[] = {
595 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
596 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
597 230400, 460800, 921600
598};
599
Tobias Klauserfe971072006-01-09 20:54:02 -0800600#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602/*****************************************************************************/
603
604/*
605 * Define the driver info for a user level control device. Used mainly
606 * to get at port stats - only not using the port device itself.
607 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700608static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 .owner = THIS_MODULE,
Alan Cox894cb912009-10-13 16:34:15 +0100610 .unlocked_ioctl = stl_memioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611};
612
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800613static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800615static void stl_cd_change(struct stlport *portp)
616{
617 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100618 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800619
Alan Coxd18a7502008-10-13 10:40:07 +0100620 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800621 return;
622
623 portp->sigs = stl_getsignals(portp);
624
625 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100626 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800627
628 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100629 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100630 tty_hangup(tty);
631 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800632}
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 * Check for any arguments passed in on the module load command line.
636 */
637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638/*****************************************************************************/
639
640/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 * Parse the supplied argument string, into the board conf struct.
642 */
643
Jiri Slaby40e82652006-12-08 02:38:41 -0800644static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800647 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Jiri Slabya0564e12006-12-08 02:38:37 -0800649 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Jiri Slaby615e4a72006-12-08 02:38:38 -0800651 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Jiri Slabyc62429d2006-12-08 02:39:14 -0800654 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800655 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Jiri Slabyc62429d2006-12-08 02:39:14 -0800657 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
659 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800660
Tobias Klauserfe971072006-01-09 20:54:02 -0800661 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800663 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
665
666 confp->brdtype = stl_brdstr[i].type;
667
668 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800669 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800670 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 i++;
672 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800673 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800674 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 i++;
676 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800677 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800678 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100679 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680}
681
682/*****************************************************************************/
683
684/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 * Allocate a new board structure. Fill out the basic info in it.
686 */
687
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800688static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800690 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800692 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800693 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700694 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800695 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800696 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100700 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703/*****************************************************************************/
704
705static int stl_open(struct tty_struct *tty, struct file *filp)
706{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800707 struct stlport *portp;
708 struct stlbrd *brdp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000709 struct tty_port *port;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800710 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000711 int portnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Jiri Slabya0564e12006-12-08 02:38:37 -0800713 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
715 minordev = tty->index;
716 brdnr = MINOR2BRD(minordev);
717 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100718 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800720 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100721 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800724 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800725 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 break;
727 if (minordev < brdp->panels[panelnr]->nrports) {
728 portnr = minordev;
729 break;
730 }
731 minordev -= brdp->panels[panelnr]->nrports;
732 }
733 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100734 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
736 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800737 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100738 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000739 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741/*
742 * On the first open of the device setup the port hardware, and
743 * initialize the per port data structure.
744 */
Alan Cox4350f3f2009-01-02 13:46:24 +0000745 tty_port_tty_set(port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 tty->driver_data = portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000747 port->count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Alan Cox4350f3f2009-01-02 13:46:24 +0000749 if ((port->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800750 if (!portp->tx.buf) {
751 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
752 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100753 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 portp->tx.head = portp->tx.buf;
755 portp->tx.tail = portp->tx.buf;
756 }
757 stl_setport(portp, tty->termios);
758 portp->sigs = stl_getsignals(portp);
759 stl_setsignals(portp, 1, 1);
760 stl_enablerxtx(portp, 1, 1);
761 stl_startrxtx(portp, 1, 0);
762 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox4350f3f2009-01-02 13:46:24 +0000763 port->flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 }
Alan Cox4350f3f2009-01-02 13:46:24 +0000765 return tty_port_block_til_ready(port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766}
767
768/*****************************************************************************/
769
Alan Cox31f35932009-01-02 13:45:05 +0000770static int stl_carrier_raised(struct tty_port *port)
771{
772 struct stlport *portp = container_of(port, struct stlport, port);
773 return (portp->sigs & TIOCM_CD) ? 1 : 0;
774}
775
Alan Coxfcc8ac12009-06-11 12:24:17 +0100776static void stl_dtr_rts(struct tty_port *port, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
Alan Cox4350f3f2009-01-02 13:46:24 +0000778 struct stlport *portp = container_of(port, struct stlport, port);
779 /* Takes brd_lock internally */
Alan Coxfcc8ac12009-06-11 12:24:17 +0100780 stl_setsignals(portp, on, on);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781}
782
783/*****************************************************************************/
784
Jiri Slaby96b066b2006-12-08 02:38:42 -0800785static void stl_flushbuffer(struct tty_struct *tty)
786{
787 struct stlport *portp;
788
789 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
790
Jiri Slaby96b066b2006-12-08 02:38:42 -0800791 portp = tty->driver_data;
792 if (portp == NULL)
793 return;
794
795 stl_flush(portp);
796 tty_wakeup(tty);
797}
798
799/*****************************************************************************/
800
801static void stl_waituntilsent(struct tty_struct *tty, int timeout)
802{
803 struct stlport *portp;
804 unsigned long tend;
805
806 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
807
Jiri Slaby96b066b2006-12-08 02:38:42 -0800808 portp = tty->driver_data;
809 if (portp == NULL)
810 return;
811
812 if (timeout == 0)
813 timeout = HZ;
814 tend = jiffies + timeout;
815
Alan Cox978e5952008-04-30 00:53:59 -0700816 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800817 while (stl_datastate(portp)) {
818 if (signal_pending(current))
819 break;
820 msleep_interruptible(20);
821 if (time_after_eq(jiffies, tend))
822 break;
823 }
Alan Cox978e5952008-04-30 00:53:59 -0700824 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800825}
826
827/*****************************************************************************/
828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829static void stl_close(struct tty_struct *tty, struct file *filp)
830{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800831 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000832 struct tty_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 unsigned long flags;
834
Jiri Slabya0564e12006-12-08 02:38:37 -0800835 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
837 portp = tty->driver_data;
Alan Coxa6614992009-01-02 13:46:50 +0000838 BUG_ON(portp == NULL);
839
Alan Cox4350f3f2009-01-02 13:46:24 +0000840 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Alan Coxa6614992009-01-02 13:46:50 +0000842 if (tty_port_close_start(port, tty, filp) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844/*
845 * May want to wait for any data to drain before closing. The BUSY
846 * flag keeps track of whether we are still sending or not - it is
847 * very accurate for the cd1400, not quite so for the sc26198.
848 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
849 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 stl_waituntilsent(tty, (HZ / 2));
851
Alan Cox4350f3f2009-01-02 13:46:24 +0000852 spin_lock_irqsave(&port->lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100853 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Cox4350f3f2009-01-02 13:46:24 +0000854 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxb65b5b52006-06-27 02:54:05 -0700855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 stl_disableintrs(portp);
857 if (tty->termios->c_cflag & HUPCL)
858 stl_setsignals(portp, 0, 0);
859 stl_enablerxtx(portp, 0, 0);
860 stl_flushbuffer(tty);
861 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800862 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800864 portp->tx.buf = NULL;
865 portp->tx.head = NULL;
866 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Alan Coxa6614992009-01-02 13:46:50 +0000869 tty_port_close_end(port, tty);
Alan Cox4350f3f2009-01-02 13:46:24 +0000870 tty_port_tty_set(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871}
872
873/*****************************************************************************/
874
875/*
876 * Write routine. Take data and stuff it in to the TX ring queue.
877 * If transmit interrupts are not running then start them.
878 */
879
880static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
881{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800882 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 unsigned int len, stlen;
884 unsigned char *chbuf;
885 char *head, *tail;
886
Jiri Slabya0564e12006-12-08 02:38:37 -0800887 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800890 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100891 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800892 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100893 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
895/*
896 * If copying direct from user space we must cater for page faults,
897 * causing us to "sleep" here for a while. To handle this copy in all
898 * the data we need now, into a local buffer. Then when we got it all
899 * copy it into the TX buffer.
900 */
901 chbuf = (unsigned char *) buf;
902
903 head = portp->tx.head;
904 tail = portp->tx.tail;
905 if (head >= tail) {
906 len = STL_TXBUFSIZE - (head - tail) - 1;
907 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
908 } else {
909 len = tail - head - 1;
910 stlen = len;
911 }
912
Jiri Slaby843b5682006-12-08 02:39:12 -0800913 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 count = 0;
915 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800916 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 memcpy(head, chbuf, stlen);
918 len -= stlen;
919 chbuf += stlen;
920 count += stlen;
921 head += stlen;
922 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
923 head = portp->tx.buf;
924 stlen = tail - head;
925 }
926 }
927 portp->tx.head = head;
928
929 clear_bit(ASYI_TXLOW, &portp->istate);
930 stl_startrxtx(portp, -1, 1);
931
Jesper Juhl014c2542006-01-15 02:37:08 +0100932 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933}
934
935/*****************************************************************************/
936
David Howells4a561222008-07-22 11:18:43 +0100937static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800939 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 unsigned int len;
941 char *head, *tail;
942
Jiri Slabya0564e12006-12-08 02:38:37 -0800943 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800946 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100947 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800948 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100949 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
951 head = portp->tx.head;
952 tail = portp->tx.tail;
953
954 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
955 len--;
956
957 if (len > 0) {
958 *head++ = ch;
959 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
960 head = portp->tx.buf;
961 }
962 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100963 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964}
965
966/*****************************************************************************/
967
968/*
969 * If there are any characters in the buffer then make sure that TX
970 * interrupts are on and get'em out. Normally used after the putchar
971 * routine has been called.
972 */
973
974static void stl_flushchars(struct tty_struct *tty)
975{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800976 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
Jiri Slabya0564e12006-12-08 02:38:37 -0800978 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800981 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800983 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 return;
985
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 stl_startrxtx(portp, -1, 1);
987}
988
989/*****************************************************************************/
990
991static int stl_writeroom(struct tty_struct *tty)
992{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800993 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 char *head, *tail;
995
Jiri Slabya0564e12006-12-08 02:38:37 -0800996 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800999 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001000 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001001 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001002 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004 head = portp->tx.head;
1005 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001006 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007}
1008
1009/*****************************************************************************/
1010
1011/*
1012 * Return number of chars in the TX buffer. Normally we would just
1013 * calculate the number of chars in the buffer and return that, but if
1014 * the buffer is empty and TX interrupts are still on then we return
1015 * that the buffer still has 1 char in it. This way whoever called us
1016 * will not think that ALL chars have drained - since the UART still
1017 * must have some chars in it (we are busy after all).
1018 */
1019
1020static int stl_charsinbuffer(struct tty_struct *tty)
1021{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001022 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 unsigned int size;
1024 char *head, *tail;
1025
Jiri Slabya0564e12006-12-08 02:38:37 -08001026 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001029 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001030 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001031 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001032 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 head = portp->tx.head;
1035 tail = portp->tx.tail;
1036 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1037 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1038 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001039 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040}
1041
1042/*****************************************************************************/
1043
1044/*
1045 * Generate the serial struct info.
1046 */
1047
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001048static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
1050 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001051 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052
Jiri Slabya0564e12006-12-08 02:38:37 -08001053 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
1055 memset(&sio, 0, sizeof(struct serial_struct));
1056 sio.line = portp->portnr;
1057 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001058 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 sio.baud_base = portp->baud_base;
1060 sio.close_delay = portp->close_delay;
1061 sio.closing_wait = portp->closing_wait;
1062 sio.custom_divisor = portp->custom_divisor;
1063 sio.hub6 = 0;
1064 if (portp->uartp == &stl_cd1400uart) {
1065 sio.type = PORT_CIRRUS;
1066 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1067 } else {
1068 sio.type = PORT_UNKNOWN;
1069 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1070 }
1071
1072 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001073 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 sio.irq = brdp->irq;
1075
1076 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1077}
1078
1079/*****************************************************************************/
1080
1081/*
1082 * Set port according to the serial struct info.
1083 * At this point we do not do any auto-configure stuff, so we will
1084 * just quietly ignore any requests to change irq, etc.
1085 */
1086
Alan Coxd18a7502008-10-13 10:40:07 +01001087static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Alan Coxd18a7502008-10-13 10:40:07 +01001089 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 struct serial_struct sio;
1091
Jiri Slabya0564e12006-12-08 02:38:37 -08001092 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
1094 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1095 return -EFAULT;
1096 if (!capable(CAP_SYS_ADMIN)) {
1097 if ((sio.baud_base != portp->baud_base) ||
1098 (sio.close_delay != portp->close_delay) ||
1099 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001100 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001101 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 }
1103
Alan Coxf8ae4762008-07-16 21:56:37 +01001104 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 (sio.flags & ASYNC_USR_MASK);
1106 portp->baud_base = sio.baud_base;
1107 portp->close_delay = sio.close_delay;
1108 portp->closing_wait = sio.closing_wait;
1109 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001110 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112}
1113
1114/*****************************************************************************/
1115
1116static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1117{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001118 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001121 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001122 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001124 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
1126 return stl_getsignals(portp);
1127}
1128
1129static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1130 unsigned int set, unsigned int clear)
1131{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001132 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 int rts = -1, dtr = -1;
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001136 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001137 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001139 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 if (set & TIOCM_RTS)
1142 rts = 1;
1143 if (set & TIOCM_DTR)
1144 dtr = 1;
1145 if (clear & TIOCM_RTS)
1146 rts = 0;
1147 if (clear & TIOCM_DTR)
1148 dtr = 0;
1149
1150 stl_setsignals(portp, dtr, rts);
1151 return 0;
1152}
1153
1154static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1155{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001156 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 int rc;
1158 void __user *argp = (void __user *)arg;
1159
Jiri Slabya0564e12006-12-08 02:38:37 -08001160 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1161 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001164 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001165 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166
1167 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001168 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001170 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172 rc = 0;
1173
Alan Coxf433c652008-04-30 00:53:23 -07001174 lock_kernel();
1175
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 case TIOCGSERIAL:
1178 rc = stl_getserial(portp, argp);
1179 break;
1180 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001181 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 break;
1183 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001184 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 break;
1186 case COM_CLRPORTSTATS:
1187 rc = stl_clrportstats(portp, argp);
1188 break;
1189 case TIOCSERCONFIG:
1190 case TIOCSERGWILD:
1191 case TIOCSERSWILD:
1192 case TIOCSERGETLSR:
1193 case TIOCSERGSTRUCT:
1194 case TIOCSERGETMULTI:
1195 case TIOCSERSETMULTI:
1196 default:
1197 rc = -ENOIOCTLCMD;
1198 break;
1199 }
Alan Coxf433c652008-04-30 00:53:23 -07001200 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001201 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202}
1203
1204/*****************************************************************************/
1205
Jiri Slaby96b066b2006-12-08 02:38:42 -08001206/*
1207 * Start the transmitter again. Just turn TX interrupts back on.
1208 */
1209
1210static void stl_start(struct tty_struct *tty)
1211{
1212 struct stlport *portp;
1213
1214 pr_debug("stl_start(tty=%p)\n", tty);
1215
Jiri Slaby96b066b2006-12-08 02:38:42 -08001216 portp = tty->driver_data;
1217 if (portp == NULL)
1218 return;
1219 stl_startrxtx(portp, -1, 1);
1220}
1221
1222/*****************************************************************************/
1223
Alan Cox606d0992006-12-08 02:38:45 -08001224static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001226 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001227 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
Jiri Slabya0564e12006-12-08 02:38:37 -08001229 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001232 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 return;
1234
1235 tiosp = tty->termios;
1236 if ((tiosp->c_cflag == old->c_cflag) &&
1237 (tiosp->c_iflag == old->c_iflag))
1238 return;
1239
1240 stl_setport(portp, tiosp);
1241 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1242 -1);
1243 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1244 tty->hw_stopped = 0;
1245 stl_start(tty);
1246 }
1247 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001248 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249}
1250
1251/*****************************************************************************/
1252
1253/*
1254 * Attempt to flow control who ever is sending us data. Based on termios
1255 * settings use software or/and hardware flow control.
1256 */
1257
1258static void stl_throttle(struct tty_struct *tty)
1259{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001260 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Jiri Slabya0564e12006-12-08 02:38:37 -08001262 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001265 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 return;
1267 stl_flowctrl(portp, 0);
1268}
1269
1270/*****************************************************************************/
1271
1272/*
1273 * Unflow control the device sending us data...
1274 */
1275
1276static void stl_unthrottle(struct tty_struct *tty)
1277{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001278 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Jiri Slabya0564e12006-12-08 02:38:37 -08001280 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001283 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return;
1285 stl_flowctrl(portp, 1);
1286}
1287
1288/*****************************************************************************/
1289
1290/*
1291 * Stop the transmitter. Basically to do this we will just turn TX
1292 * interrupts off.
1293 */
1294
1295static void stl_stop(struct tty_struct *tty)
1296{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001297 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Jiri Slabya0564e12006-12-08 02:38:37 -08001299 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001302 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 return;
1304 stl_startrxtx(portp, -1, 0);
1305}
1306
1307/*****************************************************************************/
1308
1309/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 * Hangup this port. This is pretty much like closing the port, only
1311 * a little more brutal. No waiting for data to drain. Shutdown the
1312 * port and maybe drop signals.
1313 */
1314
1315static void stl_hangup(struct tty_struct *tty)
1316{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001317 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +00001318 struct tty_port *port;
1319 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Jiri Slabya0564e12006-12-08 02:38:37 -08001321 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001324 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 return;
Alan Cox4350f3f2009-01-02 13:46:24 +00001326 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Alan Cox4350f3f2009-01-02 13:46:24 +00001328 spin_lock_irqsave(&port->lock, flags);
1329 port->flags &= ~ASYNC_INITIALIZED;
1330 spin_unlock_irqrestore(&port->lock, flags);
1331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 stl_disableintrs(portp);
1333 if (tty->termios->c_cflag & HUPCL)
1334 stl_setsignals(portp, 0, 0);
1335 stl_enablerxtx(portp, 0, 0);
1336 stl_flushbuffer(tty);
1337 portp->istate = 0;
1338 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001339 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001341 portp->tx.buf = NULL;
1342 portp->tx.head = NULL;
1343 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 }
Alan Cox4350f3f2009-01-02 13:46:24 +00001345 tty_port_hangup(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
1348/*****************************************************************************/
1349
David Howells4a561222008-07-22 11:18:43 +01001350static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001352 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Jiri Slabya0564e12006-12-08 02:38:37 -08001354 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001357 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001358 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001361 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362}
1363
1364/*****************************************************************************/
1365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366static void stl_sendxchar(struct tty_struct *tty, char ch)
1367{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001368 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Jiri Slabya0564e12006-12-08 02:38:37 -08001370 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 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
1376 if (ch == STOP_CHAR(tty))
1377 stl_sendflow(portp, 0);
1378 else if (ch == START_CHAR(tty))
1379 stl_sendflow(portp, 1);
1380 else
1381 stl_putchar(tty, ch);
1382}
1383
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001384static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001386 int sigs;
1387 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001389 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1391 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1392
1393 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001394 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001396 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001398 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001400 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001403 sep = ' ';
1404 if (sigs & TIOCM_RTS) {
1405 seq_printf(m, "%c%s", sep, "RTS");
1406 sep = '|';
1407 }
1408 if (sigs & TIOCM_CTS) {
1409 seq_printf(m, "%c%s", sep, "CTS");
1410 sep = '|';
1411 }
1412 if (sigs & TIOCM_DTR) {
1413 seq_printf(m, "%c%s", sep, "DTR");
1414 sep = '|';
1415 }
1416 if (sigs & TIOCM_CD) {
1417 seq_printf(m, "%c%s", sep, "DCD");
1418 sep = '|';
1419 }
1420 if (sigs & TIOCM_DSR) {
1421 seq_printf(m, "%c%s", sep, "DSR");
1422 sep = '|';
1423 }
1424 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425}
1426
1427/*****************************************************************************/
1428
1429/*
1430 * Port info, read from the /proc file system.
1431 */
1432
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001433static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001435 struct stlbrd *brdp;
1436 struct stlpanel *panelp;
1437 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001438 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001439 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001443 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445/*
1446 * We scan through for each board, panel and port. The offset is
1447 * calculated on the fly, and irrelevant ports are skipped.
1448 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001449 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001451 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 continue;
1453 if (brdp->state == 0)
1454 continue;
1455
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001457 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001459 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 continue;
1461
Jiri Slabyc62429d2006-12-08 02:39:14 -08001462 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 totalport++) {
1464 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001465 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001467 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 }
1469 }
1470 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001471 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472}
1473
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001474static int stl_proc_open(struct inode *inode, struct file *file)
1475{
1476 return single_open(file, stl_proc_show, NULL);
1477}
1478
1479static const struct file_operations stl_proc_fops = {
1480 .owner = THIS_MODULE,
1481 .open = stl_proc_open,
1482 .read = seq_read,
1483 .llseek = seq_lseek,
1484 .release = single_release,
1485};
1486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487/*****************************************************************************/
1488
1489/*
1490 * All board interrupts are vectored through here first. This code then
1491 * calls off to the approrpriate board interrupt handlers.
1492 */
1493
David Howells7d12e782006-10-05 14:55:46 +01001494static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001496 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
Jeff Garzika6f97b22007-10-31 05:20:49 -04001498 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
1500 return IRQ_RETVAL((* brdp->isr)(brdp));
1501}
1502
1503/*****************************************************************************/
1504
1505/*
1506 * Interrupt service routine for EasyIO board types.
1507 */
1508
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001509static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001511 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 unsigned int iobase;
1513 int handled = 0;
1514
Alan Coxb65b5b52006-06-27 02:54:05 -07001515 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 panelp = brdp->panels[0];
1517 iobase = panelp->iobase;
1518 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1519 handled = 1;
1520 (* panelp->isr)(panelp, iobase);
1521 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001522 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 return handled;
1524}
1525
1526/*****************************************************************************/
1527
1528/*
1529 * Interrupt service routine for ECH-AT board types.
1530 */
1531
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001532static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001534 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001535 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 int handled = 0;
1537
1538 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1539
1540 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1541 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001542 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 ioaddr = brdp->bnkstataddr[bnknr];
1544 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1545 panelp = brdp->bnk2panel[bnknr];
1546 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1547 }
1548 }
1549 }
1550
1551 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1552
1553 return handled;
1554}
1555
1556/*****************************************************************************/
1557
1558/*
1559 * Interrupt service routine for ECH-MCA board types.
1560 */
1561
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001562static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001564 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001565 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 int handled = 0;
1567
1568 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1569 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001570 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 ioaddr = brdp->bnkstataddr[bnknr];
1572 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1573 panelp = brdp->bnk2panel[bnknr];
1574 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1575 }
1576 }
1577 }
1578 return handled;
1579}
1580
1581/*****************************************************************************/
1582
1583/*
1584 * Interrupt service routine for ECH-PCI board types.
1585 */
1586
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001587static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001589 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001590 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 int handled = 0;
1592
1593 while (1) {
1594 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001595 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1597 ioaddr = brdp->bnkstataddr[bnknr];
1598 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1599 panelp = brdp->bnk2panel[bnknr];
1600 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1601 recheck++;
1602 handled = 1;
1603 }
1604 }
1605 if (! recheck)
1606 break;
1607 }
1608 return handled;
1609}
1610
1611/*****************************************************************************/
1612
1613/*
1614 * Interrupt service routine for ECH-8/64-PCI board types.
1615 */
1616
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001617static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001619 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001620 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 int handled = 0;
1622
1623 while (inb(brdp->ioctrl) & 0x1) {
1624 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001625 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 ioaddr = brdp->bnkstataddr[bnknr];
1627 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1628 panelp = brdp->bnk2panel[bnknr];
1629 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1630 }
1631 }
1632 }
1633
1634 return handled;
1635}
1636
1637/*****************************************************************************/
1638
1639/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 * Initialize all the ports on a panel.
1641 */
1642
Jiri Slaby705c1862006-12-08 02:39:11 -08001643static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001645 struct stlport *portp;
1646 unsigned int i;
1647 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
Jiri Slabya0564e12006-12-08 02:38:37 -08001649 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
1651 chipmask = stl_panelinit(brdp, panelp);
1652
1653/*
1654 * All UART's are initialized (if found!). Now go through and setup
1655 * each ports data structures.
1656 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001657 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001658 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001659 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001661 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 break;
1663 }
Alan Coxd18a7502008-10-13 10:40:07 +01001664 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001665 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 portp->magic = STL_PORTMAGIC;
1667 portp->portnr = i;
1668 portp->brdnr = panelp->brdnr;
1669 portp->panelnr = panelp->panelnr;
1670 portp->uartp = panelp->uartp;
1671 portp->clk = brdp->clk;
1672 portp->baud_base = STL_BAUDBASE;
1673 portp->close_delay = STL_CLOSEDELAY;
1674 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001675 init_waitqueue_head(&portp->port.open_wait);
1676 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 portp->stats.brd = portp->brdnr;
1678 portp->stats.panel = portp->panelnr;
1679 portp->stats.port = portp->portnr;
1680 panelp->ports[i] = portp;
1681 stl_portinit(brdp, panelp, portp);
1682 }
1683
Jiri Slabyc62429d2006-12-08 02:39:14 -08001684 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685}
1686
Jiri Slaby3b85b342006-12-08 02:39:10 -08001687static void stl_cleanup_panels(struct stlbrd *brdp)
1688{
1689 struct stlpanel *panelp;
1690 struct stlport *portp;
1691 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001692 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001693
1694 for (j = 0; j < STL_MAXPANELS; j++) {
1695 panelp = brdp->panels[j];
1696 if (panelp == NULL)
1697 continue;
1698 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1699 portp = panelp->ports[k];
1700 if (portp == NULL)
1701 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001702 tty = tty_port_tty_get(&portp->port);
1703 if (tty != NULL) {
1704 stl_hangup(tty);
1705 tty_kref_put(tty);
1706 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001707 kfree(portp->tx.buf);
1708 kfree(portp);
1709 }
1710 kfree(panelp);
1711 }
1712}
1713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714/*****************************************************************************/
1715
1716/*
1717 * Try to find and initialize an EasyIO board.
1718 */
1719
Jiri Slaby705c1862006-12-08 02:39:11 -08001720static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001722 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 unsigned int status;
1724 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001725 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Jiri Slabya0564e12006-12-08 02:38:37 -08001727 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
1729 brdp->ioctrl = brdp->ioaddr1 + 1;
1730 brdp->iostatus = brdp->ioaddr1 + 2;
1731
1732 status = inb(brdp->iostatus);
1733 if ((status & EIO_IDBITMASK) == EIO_MK3)
1734 brdp->ioctrl++;
1735
1736/*
1737 * Handle board specific stuff now. The real difference is PCI
1738 * or not PCI.
1739 */
1740 if (brdp->brdtype == BRD_EASYIOPCI) {
1741 brdp->iosize1 = 0x80;
1742 brdp->iosize2 = 0x80;
1743 name = "serial(EIO-PCI)";
1744 outb(0x41, (brdp->ioaddr2 + 0x4c));
1745 } else {
1746 brdp->iosize1 = 8;
1747 name = "serial(EIO)";
1748 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1749 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1750 printk("STALLION: invalid irq=%d for brd=%d\n",
1751 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001752 retval = -EINVAL;
1753 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 }
1755 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1756 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1757 brdp->ioctrl);
1758 }
1759
Jiri Slaby3b85b342006-12-08 02:39:10 -08001760 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1762 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1763 "%x conflicts with another device\n", brdp->brdnr,
1764 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001765 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 }
1767
1768 if (brdp->iosize2 > 0)
1769 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1770 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1771 "address %x conflicts with another device\n",
1772 brdp->brdnr, brdp->ioaddr2);
1773 printk(KERN_WARNING "STALLION: Warning, also "
1774 "releasing board %d I/O address %x \n",
1775 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001776 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 }
1778
1779/*
1780 * Everything looks OK, so let's go ahead and probe for the hardware.
1781 */
1782 brdp->clk = CD1400_CLK;
1783 brdp->isr = stl_eiointr;
1784
Jiri Slaby3b85b342006-12-08 02:39:10 -08001785 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 switch (status & EIO_IDBITMASK) {
1787 case EIO_8PORTM:
1788 brdp->clk = CD1400_CLK8M;
1789 /* fall thru */
1790 case EIO_8PORTRS:
1791 case EIO_8PORTDI:
1792 brdp->nrports = 8;
1793 break;
1794 case EIO_4PORTRS:
1795 brdp->nrports = 4;
1796 break;
1797 case EIO_MK3:
1798 switch (status & EIO_BRDMASK) {
1799 case ID_BRD4:
1800 brdp->nrports = 4;
1801 break;
1802 case ID_BRD8:
1803 brdp->nrports = 8;
1804 break;
1805 case ID_BRD16:
1806 brdp->nrports = 16;
1807 break;
1808 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001809 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 }
1811 break;
1812 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001813 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 }
1815
1816/*
1817 * We have verified that the board is actually present, so now we
1818 * can complete the setup.
1819 */
1820
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001821 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001822 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001824 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001825 retval = -ENOMEM;
1826 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828
1829 panelp->magic = STL_PANELMAGIC;
1830 panelp->brdnr = brdp->brdnr;
1831 panelp->panelnr = 0;
1832 panelp->nrports = brdp->nrports;
1833 panelp->iobase = brdp->ioaddr1;
1834 panelp->hwid = status;
1835 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001836 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 panelp->isr = stl_sc26198intr;
1838 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001839 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 panelp->isr = stl_cd1400eiointr;
1841 }
1842
1843 brdp->panels[0] = panelp;
1844 brdp->nrpanels = 1;
1845 brdp->state |= BRD_FOUND;
1846 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001847 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 printk("STALLION: failed to register interrupt "
1849 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001850 retval = -ENODEV;
1851 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001853
1854 return 0;
1855err_fr:
1856 stl_cleanup_panels(brdp);
1857err_rel2:
1858 if (brdp->iosize2 > 0)
1859 release_region(brdp->ioaddr2, brdp->iosize2);
1860err_rel1:
1861 release_region(brdp->ioaddr1, brdp->iosize1);
1862err:
1863 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864}
1865
1866/*****************************************************************************/
1867
1868/*
1869 * Try to find an ECH board and initialize it. This code is capable of
1870 * dealing with all types of ECH board.
1871 */
1872
Jiri Slaby705c1862006-12-08 02:39:11 -08001873static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001875 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001876 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1877 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001878 char *name;
1879
Jiri Slabya0564e12006-12-08 02:38:37 -08001880 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881
1882 status = 0;
1883 conflict = 0;
1884
1885/*
1886 * Set up the initial board register contents for boards. This varies a
1887 * bit between the different board types. So we need to handle each
1888 * separately. Also do a check that the supplied IRQ is good.
1889 */
1890 switch (brdp->brdtype) {
1891
1892 case BRD_ECH:
1893 brdp->isr = stl_echatintr;
1894 brdp->ioctrl = brdp->ioaddr1 + 1;
1895 brdp->iostatus = brdp->ioaddr1 + 1;
1896 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001897 if ((status & ECH_IDBITMASK) != ECH_ID) {
1898 retval = -ENODEV;
1899 goto err;
1900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1902 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1903 printk("STALLION: invalid irq=%d for brd=%d\n",
1904 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001905 retval = -EINVAL;
1906 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 }
1908 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1909 status |= (stl_vecmap[brdp->irq] << 1);
1910 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1911 brdp->ioctrlval = ECH_INTENABLE |
1912 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001913 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1915 brdp->iosize1 = 2;
1916 brdp->iosize2 = 32;
1917 name = "serial(EC8/32)";
1918 outb(status, brdp->ioaddr1);
1919 break;
1920
1921 case BRD_ECHMC:
1922 brdp->isr = stl_echmcaintr;
1923 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1924 brdp->iostatus = brdp->ioctrl;
1925 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001926 if ((status & ECH_IDBITMASK) != ECH_ID) {
1927 retval = -ENODEV;
1928 goto err;
1929 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1931 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1932 printk("STALLION: invalid irq=%d for brd=%d\n",
1933 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001934 retval = -EINVAL;
1935 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 }
1937 outb(ECHMC_BRDRESET, brdp->ioctrl);
1938 outb(ECHMC_INTENABLE, brdp->ioctrl);
1939 brdp->iosize1 = 64;
1940 name = "serial(EC8/32-MC)";
1941 break;
1942
1943 case BRD_ECHPCI:
1944 brdp->isr = stl_echpciintr;
1945 brdp->ioctrl = brdp->ioaddr1 + 2;
1946 brdp->iosize1 = 4;
1947 brdp->iosize2 = 8;
1948 name = "serial(EC8/32-PCI)";
1949 break;
1950
1951 case BRD_ECH64PCI:
1952 brdp->isr = stl_echpci64intr;
1953 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1954 outb(0x43, (brdp->ioaddr1 + 0x4c));
1955 brdp->iosize1 = 0x80;
1956 brdp->iosize2 = 0x80;
1957 name = "serial(EC8/64-PCI)";
1958 break;
1959
1960 default:
1961 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001962 retval = -EINVAL;
1963 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 }
1965
1966/*
1967 * Check boards for possible IO address conflicts and return fail status
1968 * if an IO conflict found.
1969 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001970 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1972 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1973 "%x conflicts with another device\n", brdp->brdnr,
1974 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001975 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 }
1977
1978 if (brdp->iosize2 > 0)
1979 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1980 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1981 "address %x conflicts with another device\n",
1982 brdp->brdnr, brdp->ioaddr2);
1983 printk(KERN_WARNING "STALLION: Warning, also "
1984 "releasing board %d I/O address %x \n",
1985 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001986 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 }
1988
1989/*
1990 * Scan through the secondary io address space looking for panels.
1991 * As we find'em allocate and initialize panel structures for each.
1992 */
1993 brdp->clk = CD1400_CLK;
1994 brdp->hwid = status;
1995
1996 ioaddr = brdp->ioaddr2;
1997 banknr = 0;
1998 panelnr = 0;
1999 nxtid = 0;
2000
Jiri Slabyc62429d2006-12-08 02:39:14 -08002001 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 if (brdp->brdtype == BRD_ECHPCI) {
2003 outb(nxtid, brdp->ioctrl);
2004 ioaddr = brdp->ioaddr2;
2005 }
2006 status = inb(ioaddr + ECH_PNLSTATUS);
2007 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002008 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002009 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002010 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002012 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002013 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002014 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 panelp->magic = STL_PANELMAGIC;
2017 panelp->brdnr = brdp->brdnr;
2018 panelp->panelnr = panelnr;
2019 panelp->iobase = ioaddr;
2020 panelp->pagenr = nxtid;
2021 panelp->hwid = status;
2022 brdp->bnk2panel[banknr] = panelp;
2023 brdp->bnkpageaddr[banknr] = nxtid;
2024 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2025
2026 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002027 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 panelp->isr = stl_sc26198intr;
2029 if (status & ECH_PNL16PORT) {
2030 panelp->nrports = 16;
2031 brdp->bnk2panel[banknr] = panelp;
2032 brdp->bnkpageaddr[banknr] = nxtid;
2033 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2034 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002035 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002038 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 panelp->isr = stl_cd1400echintr;
2040 if (status & ECH_PNL16PORT) {
2041 panelp->nrports = 16;
2042 panelp->ackmask = 0x80;
2043 if (brdp->brdtype != BRD_ECHPCI)
2044 ioaddr += EREG_BANKSIZE;
2045 brdp->bnk2panel[banknr] = panelp;
2046 brdp->bnkpageaddr[banknr] = ++nxtid;
2047 brdp->bnkstataddr[banknr++] = ioaddr +
2048 ECH_PNLSTATUS;
2049 } else {
2050 panelp->nrports = 8;
2051 panelp->ackmask = 0xc0;
2052 }
2053 }
2054
2055 nxtid++;
2056 ioaddr += EREG_BANKSIZE;
2057 brdp->nrports += panelp->nrports;
2058 brdp->panels[panelnr++] = panelp;
2059 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002060 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2061 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002062 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002063 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 }
2065
2066 brdp->nrpanels = panelnr;
2067 brdp->nrbnks = banknr;
2068 if (brdp->brdtype == BRD_ECH)
2069 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2070
2071 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002072 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 printk("STALLION: failed to register interrupt "
2074 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002075 retval = -ENODEV;
2076 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 }
2078
Jiri Slaby3b85b342006-12-08 02:39:10 -08002079 return 0;
2080err_fr:
2081 stl_cleanup_panels(brdp);
2082 if (brdp->iosize2 > 0)
2083 release_region(brdp->ioaddr2, brdp->iosize2);
2084err_rel1:
2085 release_region(brdp->ioaddr1, brdp->iosize1);
2086err:
2087 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088}
2089
2090/*****************************************************************************/
2091
2092/*
2093 * Initialize and configure the specified board.
2094 * Scan through all the boards in the configuration and see what we
2095 * can find. Handle EIO and the ECH boards a little differently here
2096 * since the initial search and setup is very different.
2097 */
2098
Jiri Slaby705c1862006-12-08 02:39:11 -08002099static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002101 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102
Jiri Slabya0564e12006-12-08 02:38:37 -08002103 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
2105 switch (brdp->brdtype) {
2106 case BRD_EASYIO:
2107 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002108 retval = stl_initeio(brdp);
2109 if (retval)
2110 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 break;
2112 case BRD_ECH:
2113 case BRD_ECHMC:
2114 case BRD_ECHPCI:
2115 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002116 retval = stl_initech(brdp);
2117 if (retval)
2118 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 break;
2120 default:
2121 printk("STALLION: board=%d is unknown board type=%d\n",
2122 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002123 retval = -ENODEV;
2124 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 if ((brdp->state & BRD_FOUND) == 0) {
2128 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2129 stl_brdnames[brdp->brdtype], brdp->brdnr,
2130 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002131 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132 }
2133
Jiri Slabyc62429d2006-12-08 02:39:14 -08002134 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002135 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 stl_initports(brdp, brdp->panels[i]);
2137
2138 printk("STALLION: %s found, board=%d io=%x irq=%d "
2139 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2140 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2141 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002142
2143 return 0;
2144err_free:
2145 free_irq(brdp->irq, brdp);
2146
2147 stl_cleanup_panels(brdp);
2148
2149 release_region(brdp->ioaddr1, brdp->iosize1);
2150 if (brdp->iosize2 > 0)
2151 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002152err:
2153 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154}
2155
2156/*****************************************************************************/
2157
2158/*
2159 * Find the next available board number that is free.
2160 */
2161
Jiri Slaby705c1862006-12-08 02:39:11 -08002162static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002164 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165
Jiri Slabyc62429d2006-12-08 02:39:14 -08002166 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002167 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 if (i >= stl_nrbrds)
2169 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002170 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002172
2173 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174}
2175
2176/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177/*
2178 * We have a Stallion board. Allocate a board structure and
2179 * initialize it. Read its IO and IRQ resources from PCI
2180 * configuration space.
2181 */
2182
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002183static int __devinit stl_pciprobe(struct pci_dev *pdev,
2184 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002186 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002187 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002188 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002190 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002191 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002192
Jiri Slaby3b85b342006-12-08 02:39:10 -08002193 retval = pci_enable_device(pdev);
2194 if (retval)
2195 goto err;
2196 brdp = stl_allocbrd();
2197 if (brdp == NULL) {
2198 retval = -ENOMEM;
2199 goto err;
2200 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002201 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002202 brdnr = stl_getbrdnr();
2203 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002204 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002206 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002207 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002208 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002210 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002211 stl_brds[brdp->brdnr] = brdp;
2212 mutex_unlock(&stl_brdslock);
2213
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002215 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
2217/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 * We have all resources from the board, so let's setup the actual
2219 * board structure now.
2220 */
2221 switch (brdtype) {
2222 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002223 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2224 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 break;
2226 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002227 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2228 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 break;
2230 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002231 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2232 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 break;
2234 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002235 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 break;
2237 }
2238
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002239 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002240 retval = stl_brdinit(brdp);
2241 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002242 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002244 pci_set_drvdata(pdev, brdp);
2245
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002246 for (i = 0; i < brdp->nrports; i++)
2247 tty_register_device(stl_serial,
2248 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2249
Jiri Slaby3b85b342006-12-08 02:39:10 -08002250 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002251err_null:
2252 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002253err_fr:
2254 kfree(brdp);
2255err:
2256 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257}
2258
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002259static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002261 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002262 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002264 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002266 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002268 release_region(brdp->ioaddr1, brdp->iosize1);
2269 if (brdp->iosize2 > 0)
2270 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002272 for (i = 0; i < brdp->nrports; i++)
2273 tty_unregister_device(stl_serial,
2274 brdp->brdnr * STL_MAXPORTS + i);
2275
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002276 stl_brds[brdp->brdnr] = NULL;
2277 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278}
2279
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002280static struct pci_driver stl_pcidriver = {
2281 .name = "stallion",
2282 .id_table = stl_pcibrds,
2283 .probe = stl_pciprobe,
2284 .remove = __devexit_p(stl_pciremove)
2285};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
2287/*****************************************************************************/
2288
2289/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 * Return the board stats structure to user app.
2291 */
2292
2293static int stl_getbrdstats(combrd_t __user *bp)
2294{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002295 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002296 struct stlbrd *brdp;
2297 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002298 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
2300 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2301 return -EFAULT;
2302 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002303 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002305 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002306 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
2308 memset(&stl_brdstats, 0, sizeof(combrd_t));
2309 stl_brdstats.brd = brdp->brdnr;
2310 stl_brdstats.type = brdp->brdtype;
2311 stl_brdstats.hwid = brdp->hwid;
2312 stl_brdstats.state = brdp->state;
2313 stl_brdstats.ioaddr = brdp->ioaddr1;
2314 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2315 stl_brdstats.irq = brdp->irq;
2316 stl_brdstats.nrpanels = brdp->nrpanels;
2317 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002318 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 panelp = brdp->panels[i];
2320 stl_brdstats.panels[i].panel = i;
2321 stl_brdstats.panels[i].hwid = panelp->hwid;
2322 stl_brdstats.panels[i].nrports = panelp->nrports;
2323 }
2324
2325 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2326}
2327
2328/*****************************************************************************/
2329
2330/*
2331 * Resolve the referenced port number into a port struct pointer.
2332 */
2333
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002334static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002336 struct stlbrd *brdp;
2337 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
Jiri Slabyc62429d2006-12-08 02:39:14 -08002339 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2340 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002342 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002343 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002344 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002345 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002347 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002348 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002349 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002350 return NULL;
2351 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352}
2353
2354/*****************************************************************************/
2355
2356/*
2357 * Return the port stats structure to user app. A NULL port struct
2358 * pointer passed in means that we need to find out from the app
2359 * what port to get stats for (used through board control device).
2360 */
2361
Alan Coxd18a7502008-10-13 10:40:07 +01002362static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002364 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 unsigned char *head, *tail;
2366 unsigned long flags;
2367
2368 if (!portp) {
2369 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2370 return -EFAULT;
2371 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2372 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002373 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002374 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 }
2376
2377 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002378 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 portp->stats.hwid = portp->hwid;
2380
2381 portp->stats.ttystate = 0;
2382 portp->stats.cflags = 0;
2383 portp->stats.iflags = 0;
2384 portp->stats.oflags = 0;
2385 portp->stats.lflags = 0;
2386 portp->stats.rxbuffered = 0;
2387
Alan Coxb65b5b52006-06-27 02:54:05 -07002388 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002389 if (tty != NULL && portp->port.tty == tty) {
2390 portp->stats.ttystate = tty->flags;
2391 /* No longer available as a statistic */
2392 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2393 if (tty->termios != NULL) {
2394 portp->stats.cflags = tty->termios->c_cflag;
2395 portp->stats.iflags = tty->termios->c_iflag;
2396 portp->stats.oflags = tty->termios->c_oflag;
2397 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
Alan Coxd18a7502008-10-13 10:40:07 +01002399 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002400 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
2402 head = portp->tx.head;
2403 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002404 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2405 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
2407 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2408
2409 return copy_to_user(cp, &portp->stats,
2410 sizeof(comstats_t)) ? -EFAULT : 0;
2411}
2412
2413/*****************************************************************************/
2414
2415/*
2416 * Clear the port stats structure. We also return it zeroed out...
2417 */
2418
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002419static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002421 comstats_t stl_comstats;
2422
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 if (!portp) {
2424 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2425 return -EFAULT;
2426 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2427 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002428 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002429 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 }
2431
2432 memset(&portp->stats, 0, sizeof(comstats_t));
2433 portp->stats.brd = portp->brdnr;
2434 portp->stats.panel = portp->panelnr;
2435 portp->stats.port = portp->portnr;
2436 return copy_to_user(cp, &portp->stats,
2437 sizeof(comstats_t)) ? -EFAULT : 0;
2438}
2439
2440/*****************************************************************************/
2441
2442/*
2443 * Return the entire driver ports structure to a user app.
2444 */
2445
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002446static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002448 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002449 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002451 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 return -EFAULT;
2453 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2454 stl_dummyport.portnr);
2455 if (!portp)
2456 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002457 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458}
2459
2460/*****************************************************************************/
2461
2462/*
2463 * Return the entire driver board structure to a user app.
2464 */
2465
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002466static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002468 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002469 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002471 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002473 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 return -ENODEV;
2475 brdp = stl_brds[stl_dummybrd.brdnr];
2476 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002477 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002478 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479}
2480
2481/*****************************************************************************/
2482
2483/*
2484 * The "staliomem" device is also required to do some special operations
2485 * on the board and/or ports. In this driver it is mostly used for stats
2486 * collection.
2487 */
2488
Alan Cox894cb912009-10-13 16:34:15 +01002489static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490{
2491 int brdnr, rc;
2492 void __user *argp = (void __user *)arg;
2493
Alan Cox894cb912009-10-13 16:34:15 +01002494 pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Alan Cox894cb912009-10-13 16:34:15 +01002496 brdnr = iminor(fp->f_dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002498 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 rc = 0;
2500
Alan Cox894cb912009-10-13 16:34:15 +01002501 lock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 switch (cmd) {
2503 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002504 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 break;
2506 case COM_CLRPORTSTATS:
2507 rc = stl_clrportstats(NULL, argp);
2508 break;
2509 case COM_GETBRDSTATS:
2510 rc = stl_getbrdstats(argp);
2511 break;
2512 case COM_READPORT:
2513 rc = stl_getportstruct(argp);
2514 break;
2515 case COM_READBOARD:
2516 rc = stl_getbrdstruct(argp);
2517 break;
2518 default:
2519 rc = -ENOIOCTLCMD;
2520 break;
2521 }
Alan Cox894cb912009-10-13 16:34:15 +01002522 unlock_kernel();
Jiri Slabyc62429d2006-12-08 02:39:14 -08002523 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524}
2525
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002526static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 .open = stl_open,
2528 .close = stl_close,
2529 .write = stl_write,
2530 .put_char = stl_putchar,
2531 .flush_chars = stl_flushchars,
2532 .write_room = stl_writeroom,
2533 .chars_in_buffer = stl_charsinbuffer,
2534 .ioctl = stl_ioctl,
2535 .set_termios = stl_settermios,
2536 .throttle = stl_throttle,
2537 .unthrottle = stl_unthrottle,
2538 .stop = stl_stop,
2539 .start = stl_start,
2540 .hangup = stl_hangup,
2541 .flush_buffer = stl_flushbuffer,
2542 .break_ctl = stl_breakctl,
2543 .wait_until_sent = stl_waituntilsent,
2544 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 .tiocmget = stl_tiocmget,
2546 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002547 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548};
2549
Alan Cox31f35932009-01-02 13:45:05 +00002550static const struct tty_port_operations stl_port_ops = {
2551 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002552 .dtr_rts = stl_dtr_rts,
Alan Cox31f35932009-01-02 13:45:05 +00002553};
2554
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556/* CD1400 HARDWARE FUNCTIONS */
2557/*****************************************************************************/
2558
2559/*
2560 * These functions get/set/update the registers of the cd1400 UARTs.
2561 * Access to the cd1400 registers is via an address/data io port pair.
2562 * (Maybe should make this inline...)
2563 */
2564
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002565static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566{
2567 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002568 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569}
2570
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002571static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002573 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 outb(value, portp->ioaddr + EREG_DATA);
2575}
2576
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002577static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002579 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if (inb(portp->ioaddr + EREG_DATA) != value) {
2581 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002582 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002584 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585}
2586
2587/*****************************************************************************/
2588
2589/*
2590 * Inbitialize the UARTs in a panel. We don't care what sort of board
2591 * these ports are on - since the port io registers are almost
2592 * identical when dealing with ports.
2593 */
2594
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002595static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596{
2597 unsigned int gfrcr;
2598 int chipmask, i, j;
2599 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002600 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
Jiri Slabya0564e12006-12-08 02:38:37 -08002602 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
Alan Coxb65b5b52006-06-27 02:54:05 -07002604 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 BRDENABLE(panelp->brdnr, panelp->pagenr);
2606
2607/*
2608 * Check that each chip is present and started up OK.
2609 */
2610 chipmask = 0;
2611 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002612 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 if (brdp->brdtype == BRD_ECHPCI) {
2614 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2615 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002616 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 uartaddr = (i & 0x01) ? 0x080 : 0;
2619 outb((GFRCR + uartaddr), ioaddr);
2620 outb(0, (ioaddr + EREG_DATA));
2621 outb((CCR + uartaddr), ioaddr);
2622 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2623 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2624 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002625 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2627 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002628
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2630 printk("STALLION: cd1400 not responding, "
2631 "brd=%d panel=%d chip=%d\n",
2632 panelp->brdnr, panelp->panelnr, i);
2633 continue;
2634 }
2635 chipmask |= (0x1 << i);
2636 outb((PPR + uartaddr), ioaddr);
2637 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2638 }
2639
2640 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002641 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002642 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643}
2644
2645/*****************************************************************************/
2646
2647/*
2648 * Initialize hardware specific port registers.
2649 */
2650
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002651static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652{
Alan Coxb65b5b52006-06-27 02:54:05 -07002653 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002654 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2655 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
Jiri Slaby615e4a72006-12-08 02:38:38 -08002657 if ((brdp == NULL) || (panelp == NULL) ||
2658 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 return;
2660
Alan Coxb65b5b52006-06-27 02:54:05 -07002661 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2663 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2664 portp->uartaddr = (portp->portnr & 0x04) << 5;
2665 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2666
2667 BRDENABLE(portp->brdnr, portp->pagenr);
2668 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2669 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2670 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2671 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002672 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673}
2674
2675/*****************************************************************************/
2676
2677/*
2678 * Wait for the command register to be ready. We will poll this,
2679 * since it won't usually take too long to be ready.
2680 */
2681
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002682static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683{
2684 int i;
2685
Jiri Slabyc62429d2006-12-08 02:39:14 -08002686 for (i = 0; i < CCR_MAXWAIT; i++)
2687 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
2690 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2691 portp->portnr, portp->panelnr, portp->brdnr);
2692}
2693
2694/*****************************************************************************/
2695
2696/*
2697 * Set up the cd1400 registers for a port based on the termios port
2698 * settings.
2699 */
2700
Alan Cox606d0992006-12-08 02:38:45 -08002701static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002703 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 unsigned long flags;
2705 unsigned int clkdiv, baudrate;
2706 unsigned char cor1, cor2, cor3;
2707 unsigned char cor4, cor5, ccr;
2708 unsigned char srer, sreron, sreroff;
2709 unsigned char mcor1, mcor2, rtpr;
2710 unsigned char clk, div;
2711
2712 cor1 = 0;
2713 cor2 = 0;
2714 cor3 = 0;
2715 cor4 = 0;
2716 cor5 = 0;
2717 ccr = 0;
2718 rtpr = 0;
2719 clk = 0;
2720 div = 0;
2721 mcor1 = 0;
2722 mcor2 = 0;
2723 sreron = 0;
2724 sreroff = 0;
2725
2726 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002727 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 return;
2729
2730/*
2731 * Set up the RX char ignore mask with those RX error types we
2732 * can ignore. We can get the cd1400 to help us out a little here,
2733 * it will ignore parity errors and breaks for us.
2734 */
2735 portp->rxignoremsk = 0;
2736 if (tiosp->c_iflag & IGNPAR) {
2737 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2738 cor1 |= COR1_PARIGNORE;
2739 }
2740 if (tiosp->c_iflag & IGNBRK) {
2741 portp->rxignoremsk |= ST_BREAK;
2742 cor4 |= COR4_IGNBRK;
2743 }
2744
2745 portp->rxmarkmsk = ST_OVERRUN;
2746 if (tiosp->c_iflag & (INPCK | PARMRK))
2747 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2748 if (tiosp->c_iflag & BRKINT)
2749 portp->rxmarkmsk |= ST_BREAK;
2750
2751/*
2752 * Go through the char size, parity and stop bits and set all the
2753 * option register appropriately.
2754 */
2755 switch (tiosp->c_cflag & CSIZE) {
2756 case CS5:
2757 cor1 |= COR1_CHL5;
2758 break;
2759 case CS6:
2760 cor1 |= COR1_CHL6;
2761 break;
2762 case CS7:
2763 cor1 |= COR1_CHL7;
2764 break;
2765 default:
2766 cor1 |= COR1_CHL8;
2767 break;
2768 }
2769
2770 if (tiosp->c_cflag & CSTOPB)
2771 cor1 |= COR1_STOP2;
2772 else
2773 cor1 |= COR1_STOP1;
2774
2775 if (tiosp->c_cflag & PARENB) {
2776 if (tiosp->c_cflag & PARODD)
2777 cor1 |= (COR1_PARENB | COR1_PARODD);
2778 else
2779 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2780 } else {
2781 cor1 |= COR1_PARNONE;
2782 }
2783
2784/*
2785 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2786 * space for hardware flow control and the like. This should be set to
2787 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2788 * really be based on VTIME.
2789 */
2790 cor3 |= FIFO_RXTHRESHOLD;
2791 rtpr = 2;
2792
2793/*
2794 * Calculate the baud rate timers. For now we will just assume that
2795 * the input and output baud are the same. Could have used a baud
2796 * table here, but this way we can generate virtually any baud rate
2797 * we like!
2798 */
2799 baudrate = tiosp->c_cflag & CBAUD;
2800 if (baudrate & CBAUDEX) {
2801 baudrate &= ~CBAUDEX;
2802 if ((baudrate < 1) || (baudrate > 4))
2803 tiosp->c_cflag &= ~CBAUDEX;
2804 else
2805 baudrate += 15;
2806 }
2807 baudrate = stl_baudrates[baudrate];
2808 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002809 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002811 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002813 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002815 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002817 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 baudrate = (portp->baud_base / portp->custom_divisor);
2819 }
2820 if (baudrate > STL_CD1400MAXBAUD)
2821 baudrate = STL_CD1400MAXBAUD;
2822
2823 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002824 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2825 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 if (clkdiv < 0x100)
2827 break;
2828 }
2829 div = (unsigned char) clkdiv;
2830 }
2831
2832/*
2833 * Check what form of modem signaling is required and set it up.
2834 */
2835 if ((tiosp->c_cflag & CLOCAL) == 0) {
2836 mcor1 |= MCOR1_DCD;
2837 mcor2 |= MCOR2_DCD;
2838 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002839 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002840 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002841 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
2843/*
2844 * Setup cd1400 enhanced modes if we can. In particular we want to
2845 * handle as much of the flow control as possible automatically. As
2846 * well as saving a few CPU cycles it will also greatly improve flow
2847 * control reliability.
2848 */
2849 if (tiosp->c_iflag & IXON) {
2850 cor2 |= COR2_TXIBE;
2851 cor3 |= COR3_SCD12;
2852 if (tiosp->c_iflag & IXANY)
2853 cor2 |= COR2_IXM;
2854 }
2855
2856 if (tiosp->c_cflag & CRTSCTS) {
2857 cor2 |= COR2_CTSAE;
2858 mcor1 |= FIFO_RTSTHRESHOLD;
2859 }
2860
2861/*
2862 * All cd1400 register values calculated so go through and set
2863 * them all up.
2864 */
2865
Jiri Slabya0564e12006-12-08 02:38:37 -08002866 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002868 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002870 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002872 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2873 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2875 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
Alan Coxb65b5b52006-06-27 02:54:05 -07002877 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 BRDENABLE(portp->brdnr, portp->pagenr);
2879 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2880 srer = stl_cd1400getreg(portp, SRER);
2881 stl_cd1400setreg(portp, SRER, 0);
2882 if (stl_cd1400updatereg(portp, COR1, cor1))
2883 ccr = 1;
2884 if (stl_cd1400updatereg(portp, COR2, cor2))
2885 ccr = 1;
2886 if (stl_cd1400updatereg(portp, COR3, cor3))
2887 ccr = 1;
2888 if (ccr) {
2889 stl_cd1400ccrwait(portp);
2890 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2891 }
2892 stl_cd1400setreg(portp, COR4, cor4);
2893 stl_cd1400setreg(portp, COR5, cor5);
2894 stl_cd1400setreg(portp, MCOR1, mcor1);
2895 stl_cd1400setreg(portp, MCOR2, mcor2);
2896 if (baudrate > 0) {
2897 stl_cd1400setreg(portp, TCOR, clk);
2898 stl_cd1400setreg(portp, TBPR, div);
2899 stl_cd1400setreg(portp, RCOR, clk);
2900 stl_cd1400setreg(portp, RBPR, div);
2901 }
2902 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2903 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2904 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2905 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2906 stl_cd1400setreg(portp, RTPR, rtpr);
2907 mcor1 = stl_cd1400getreg(portp, MSVR1);
2908 if (mcor1 & MSVR1_DCD)
2909 portp->sigs |= TIOCM_CD;
2910 else
2911 portp->sigs &= ~TIOCM_CD;
2912 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2913 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002914 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915}
2916
2917/*****************************************************************************/
2918
2919/*
2920 * Set the state of the DTR and RTS signals.
2921 */
2922
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002923static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924{
2925 unsigned char msvr1, msvr2;
2926 unsigned long flags;
2927
Jiri Slabya0564e12006-12-08 02:38:37 -08002928 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2929 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 msvr1 = 0;
2932 msvr2 = 0;
2933 if (dtr > 0)
2934 msvr1 = MSVR1_DTR;
2935 if (rts > 0)
2936 msvr2 = MSVR2_RTS;
2937
Alan Coxb65b5b52006-06-27 02:54:05 -07002938 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 BRDENABLE(portp->brdnr, portp->pagenr);
2940 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2941 if (rts >= 0)
2942 stl_cd1400setreg(portp, MSVR2, msvr2);
2943 if (dtr >= 0)
2944 stl_cd1400setreg(portp, MSVR1, msvr1);
2945 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002946 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947}
2948
2949/*****************************************************************************/
2950
2951/*
2952 * Return the state of the signals.
2953 */
2954
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002955static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956{
2957 unsigned char msvr1, msvr2;
2958 unsigned long flags;
2959 int sigs;
2960
Jiri Slabya0564e12006-12-08 02:38:37 -08002961 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962
Alan Coxb65b5b52006-06-27 02:54:05 -07002963 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 BRDENABLE(portp->brdnr, portp->pagenr);
2965 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2966 msvr1 = stl_cd1400getreg(portp, MSVR1);
2967 msvr2 = stl_cd1400getreg(portp, MSVR2);
2968 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002969 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
2971 sigs = 0;
2972 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2973 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2974 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2975 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2976#if 0
2977 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2978 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2979#else
2980 sigs |= TIOCM_DSR;
2981#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002982 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983}
2984
2985/*****************************************************************************/
2986
2987/*
2988 * Enable/Disable the Transmitter and/or Receiver.
2989 */
2990
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002991static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992{
2993 unsigned char ccr;
2994 unsigned long flags;
2995
Jiri Slabya0564e12006-12-08 02:38:37 -08002996 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2997
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 ccr = 0;
2999
3000 if (tx == 0)
3001 ccr |= CCR_TXDISABLE;
3002 else if (tx > 0)
3003 ccr |= CCR_TXENABLE;
3004 if (rx == 0)
3005 ccr |= CCR_RXDISABLE;
3006 else if (rx > 0)
3007 ccr |= CCR_RXENABLE;
3008
Alan Coxb65b5b52006-06-27 02:54:05 -07003009 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 BRDENABLE(portp->brdnr, portp->pagenr);
3011 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3012 stl_cd1400ccrwait(portp);
3013 stl_cd1400setreg(portp, CCR, ccr);
3014 stl_cd1400ccrwait(portp);
3015 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003016 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017}
3018
3019/*****************************************************************************/
3020
3021/*
3022 * Start/stop the Transmitter and/or Receiver.
3023 */
3024
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003025static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026{
3027 unsigned char sreron, sreroff;
3028 unsigned long flags;
3029
Jiri Slabya0564e12006-12-08 02:38:37 -08003030 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
3032 sreron = 0;
3033 sreroff = 0;
3034 if (tx == 0)
3035 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3036 else if (tx == 1)
3037 sreron |= SRER_TXDATA;
3038 else if (tx >= 2)
3039 sreron |= SRER_TXEMPTY;
3040 if (rx == 0)
3041 sreroff |= SRER_RXDATA;
3042 else if (rx > 0)
3043 sreron |= SRER_RXDATA;
3044
Alan Coxb65b5b52006-06-27 02:54:05 -07003045 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 BRDENABLE(portp->brdnr, portp->pagenr);
3047 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3048 stl_cd1400setreg(portp, SRER,
3049 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3050 BRDDISABLE(portp->brdnr);
3051 if (tx > 0)
3052 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003053 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054}
3055
3056/*****************************************************************************/
3057
3058/*
3059 * Disable all interrupts from this port.
3060 */
3061
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003062static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063{
3064 unsigned long flags;
3065
Jiri Slabya0564e12006-12-08 02:38:37 -08003066 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3067
Alan Coxb65b5b52006-06-27 02:54:05 -07003068 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 BRDENABLE(portp->brdnr, portp->pagenr);
3070 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3071 stl_cd1400setreg(portp, SRER, 0);
3072 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003073 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074}
3075
3076/*****************************************************************************/
3077
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003078static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079{
3080 unsigned long flags;
3081
Jiri Slabya0564e12006-12-08 02:38:37 -08003082 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
Alan Coxb65b5b52006-06-27 02:54:05 -07003084 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 BRDENABLE(portp->brdnr, portp->pagenr);
3086 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3087 stl_cd1400setreg(portp, SRER,
3088 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3089 SRER_TXEMPTY));
3090 BRDDISABLE(portp->brdnr);
3091 portp->brklen = len;
3092 if (len == 1)
3093 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003094 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095}
3096
3097/*****************************************************************************/
3098
3099/*
3100 * Take flow control actions...
3101 */
3102
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003103static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104{
3105 struct tty_struct *tty;
3106 unsigned long flags;
3107
Jiri Slabya0564e12006-12-08 02:38:37 -08003108 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
Jiri Slaby615e4a72006-12-08 02:38:38 -08003110 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003112 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003113 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 return;
3115
Alan Coxb65b5b52006-06-27 02:54:05 -07003116 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 BRDENABLE(portp->brdnr, portp->pagenr);
3118 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3119
3120 if (state) {
3121 if (tty->termios->c_iflag & IXOFF) {
3122 stl_cd1400ccrwait(portp);
3123 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3124 portp->stats.rxxon++;
3125 stl_cd1400ccrwait(portp);
3126 }
3127/*
3128 * Question: should we return RTS to what it was before? It may
3129 * have been set by an ioctl... Suppose not, since if you have
3130 * hardware flow control set then it is pretty silly to go and
3131 * set the RTS line by hand.
3132 */
3133 if (tty->termios->c_cflag & CRTSCTS) {
3134 stl_cd1400setreg(portp, MCOR1,
3135 (stl_cd1400getreg(portp, MCOR1) |
3136 FIFO_RTSTHRESHOLD));
3137 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3138 portp->stats.rxrtson++;
3139 }
3140 } else {
3141 if (tty->termios->c_iflag & IXOFF) {
3142 stl_cd1400ccrwait(portp);
3143 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3144 portp->stats.rxxoff++;
3145 stl_cd1400ccrwait(portp);
3146 }
3147 if (tty->termios->c_cflag & CRTSCTS) {
3148 stl_cd1400setreg(portp, MCOR1,
3149 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3150 stl_cd1400setreg(portp, MSVR2, 0);
3151 portp->stats.rxrtsoff++;
3152 }
3153 }
3154
3155 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003156 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003157 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158}
3159
3160/*****************************************************************************/
3161
3162/*
3163 * Send a flow control character...
3164 */
3165
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003166static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167{
3168 struct tty_struct *tty;
3169 unsigned long flags;
3170
Jiri Slabya0564e12006-12-08 02:38:37 -08003171 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172
Jiri Slaby615e4a72006-12-08 02:38:38 -08003173 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003175 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003176 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 return;
3178
Alan Coxb65b5b52006-06-27 02:54:05 -07003179 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 BRDENABLE(portp->brdnr, portp->pagenr);
3181 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3182 if (state) {
3183 stl_cd1400ccrwait(portp);
3184 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3185 portp->stats.rxxon++;
3186 stl_cd1400ccrwait(portp);
3187 } else {
3188 stl_cd1400ccrwait(portp);
3189 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3190 portp->stats.rxxoff++;
3191 stl_cd1400ccrwait(portp);
3192 }
3193 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003194 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003195 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196}
3197
3198/*****************************************************************************/
3199
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003200static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201{
3202 unsigned long flags;
3203
Jiri Slabya0564e12006-12-08 02:38:37 -08003204 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
Jiri Slaby615e4a72006-12-08 02:38:38 -08003206 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 return;
3208
Alan Coxb65b5b52006-06-27 02:54:05 -07003209 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 BRDENABLE(portp->brdnr, portp->pagenr);
3211 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3212 stl_cd1400ccrwait(portp);
3213 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3214 stl_cd1400ccrwait(portp);
3215 portp->tx.tail = portp->tx.head;
3216 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003217 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218}
3219
3220/*****************************************************************************/
3221
3222/*
3223 * Return the current state of data flow on this port. This is only
3224 * really interresting when determining if data has fully completed
3225 * transmission or not... This is easy for the cd1400, it accurately
3226 * maintains the busy port flag.
3227 */
3228
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003229static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230{
Jiri Slabya0564e12006-12-08 02:38:37 -08003231 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232
Jiri Slaby615e4a72006-12-08 02:38:38 -08003233 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003234 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235
Jesper Juhl014c2542006-01-15 02:37:08 +01003236 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237}
3238
3239/*****************************************************************************/
3240
3241/*
3242 * Interrupt service routine for cd1400 EasyIO boards.
3243 */
3244
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003245static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246{
3247 unsigned char svrtype;
3248
Jiri Slabya0564e12006-12-08 02:38:37 -08003249 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Alan Coxb65b5b52006-06-27 02:54:05 -07003251 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 outb(SVRR, iobase);
3253 svrtype = inb(iobase + EREG_DATA);
3254 if (panelp->nrports > 4) {
3255 outb((SVRR + 0x80), iobase);
3256 svrtype |= inb(iobase + EREG_DATA);
3257 }
3258
3259 if (svrtype & SVRR_RX)
3260 stl_cd1400rxisr(panelp, iobase);
3261 else if (svrtype & SVRR_TX)
3262 stl_cd1400txisr(panelp, iobase);
3263 else if (svrtype & SVRR_MDM)
3264 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003265
3266 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267}
3268
3269/*****************************************************************************/
3270
3271/*
3272 * Interrupt service routine for cd1400 panels.
3273 */
3274
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003275static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276{
3277 unsigned char svrtype;
3278
Jiri Slabya0564e12006-12-08 02:38:37 -08003279 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
3281 outb(SVRR, iobase);
3282 svrtype = inb(iobase + EREG_DATA);
3283 outb((SVRR + 0x80), iobase);
3284 svrtype |= inb(iobase + EREG_DATA);
3285 if (svrtype & SVRR_RX)
3286 stl_cd1400rxisr(panelp, iobase);
3287 else if (svrtype & SVRR_TX)
3288 stl_cd1400txisr(panelp, iobase);
3289 else if (svrtype & SVRR_MDM)
3290 stl_cd1400mdmisr(panelp, iobase);
3291}
3292
3293
3294/*****************************************************************************/
3295
3296/*
3297 * Unfortunately we need to handle breaks in the TX data stream, since
3298 * this is the only way to generate them on the cd1400.
3299 */
3300
Jiri Slaby60be4812006-12-08 02:38:40 -08003301static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302{
3303 if (portp->brklen == 1) {
3304 outb((COR2 + portp->uartaddr), ioaddr);
3305 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3306 (ioaddr + EREG_DATA));
3307 outb((TDR + portp->uartaddr), ioaddr);
3308 outb(ETC_CMD, (ioaddr + EREG_DATA));
3309 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3310 outb((SRER + portp->uartaddr), ioaddr);
3311 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3312 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003313 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 } else if (portp->brklen > 1) {
3315 outb((TDR + portp->uartaddr), ioaddr);
3316 outb(ETC_CMD, (ioaddr + EREG_DATA));
3317 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3318 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003319 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320 } else {
3321 outb((COR2 + portp->uartaddr), ioaddr);
3322 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3323 (ioaddr + EREG_DATA));
3324 portp->brklen = 0;
3325 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003326 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327}
3328
3329/*****************************************************************************/
3330
3331/*
3332 * Transmit interrupt handler. This has gotta be fast! Handling TX
3333 * chars is pretty simple, stuff as many as possible from the TX buffer
3334 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3335 * are embedded as commands in the data stream. Oh no, had to use a goto!
3336 * This could be optimized more, will do when I get time...
3337 * In practice it is possible that interrupts are enabled but that the
3338 * port has been hung up. Need to handle not having any TX buffer here,
3339 * this is done by using the side effect that head and tail will also
3340 * be NULL if the buffer has been freed.
3341 */
3342
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003343static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003345 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 int len, stlen;
3347 char *head, *tail;
3348 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003349 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350
Jiri Slabya0564e12006-12-08 02:38:37 -08003351 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
3353 ioack = inb(ioaddr + EREG_TXACK);
3354 if (((ioack & panelp->ackmask) != 0) ||
3355 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3356 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3357 return;
3358 }
3359 portp = panelp->ports[(ioack >> 3)];
3360
3361/*
3362 * Unfortunately we need to handle breaks in the data stream, since
3363 * this is the only way to generate them on the cd1400. Do it now if
3364 * a break is to be sent.
3365 */
3366 if (portp->brklen != 0)
3367 if (stl_cd1400breakisr(portp, ioaddr))
3368 goto stl_txalldone;
3369
3370 head = portp->tx.head;
3371 tail = portp->tx.tail;
3372 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3373 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3374 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3375 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003376 tty = tty_port_tty_get(&portp->port);
3377 if (tty) {
3378 tty_wakeup(tty);
3379 tty_kref_put(tty);
3380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 }
3382
3383 if (len == 0) {
3384 outb((SRER + portp->uartaddr), ioaddr);
3385 srer = inb(ioaddr + EREG_DATA);
3386 if (srer & SRER_TXDATA) {
3387 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3388 } else {
3389 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3390 clear_bit(ASYI_TXBUSY, &portp->istate);
3391 }
3392 outb(srer, (ioaddr + EREG_DATA));
3393 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003394 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003396 stlen = min_t(unsigned int, len,
3397 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 outb((TDR + portp->uartaddr), ioaddr);
3399 outsb((ioaddr + EREG_DATA), tail, stlen);
3400 len -= stlen;
3401 tail += stlen;
3402 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3403 tail = portp->tx.buf;
3404 if (len > 0) {
3405 outsb((ioaddr + EREG_DATA), tail, len);
3406 tail += len;
3407 }
3408 portp->tx.tail = tail;
3409 }
3410
3411stl_txalldone:
3412 outb((EOSRR + portp->uartaddr), ioaddr);
3413 outb(0, (ioaddr + EREG_DATA));
3414}
3415
3416/*****************************************************************************/
3417
3418/*
3419 * Receive character interrupt handler. Determine if we have good chars
3420 * or bad chars and then process appropriately. Good chars are easy
3421 * just shove the lot into the RX buffer and set all status byte to 0.
3422 * If a bad RX char then process as required. This routine needs to be
3423 * fast! In practice it is possible that we get an interrupt on a port
3424 * that is closed. This can happen on hangups - since they completely
3425 * shutdown a port not in user context. Need to handle this case.
3426 */
3427
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003428static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003430 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 struct tty_struct *tty;
3432 unsigned int ioack, len, buflen;
3433 unsigned char status;
3434 char ch;
3435
Jiri Slabya0564e12006-12-08 02:38:37 -08003436 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
3438 ioack = inb(ioaddr + EREG_RXACK);
3439 if ((ioack & panelp->ackmask) != 0) {
3440 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3441 return;
3442 }
3443 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003444 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445
3446 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3447 outb((RDCR + portp->uartaddr), ioaddr);
3448 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003449 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003450 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 outb((RDSR + portp->uartaddr), ioaddr);
3452 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3453 portp->stats.rxlost += len;
3454 portp->stats.rxtotal += len;
3455 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003456 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003458 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003460 tty_prepare_flip_string(tty, &ptr, len);
3461 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 tty_schedule_flip(tty);
3463 portp->stats.rxtotal += len;
3464 }
3465 }
3466 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3467 outb((RDSR + portp->uartaddr), ioaddr);
3468 status = inb(ioaddr + EREG_DATA);
3469 ch = inb(ioaddr + EREG_DATA);
3470 if (status & ST_PARITY)
3471 portp->stats.rxparity++;
3472 if (status & ST_FRAMING)
3473 portp->stats.rxframing++;
3474 if (status & ST_OVERRUN)
3475 portp->stats.rxoverrun++;
3476 if (status & ST_BREAK)
3477 portp->stats.rxbreaks++;
3478 if (status & ST_SCHARMASK) {
3479 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3480 portp->stats.txxon++;
3481 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3482 portp->stats.txxoff++;
3483 goto stl_rxalldone;
3484 }
Alan Cox33f0f882006-01-09 20:54:13 -08003485 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 if (portp->rxmarkmsk & status) {
3487 if (status & ST_BREAK) {
3488 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003489 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003490 do_SAK(tty);
3491 BRDENABLE(portp->brdnr, portp->pagenr);
3492 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003493 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003495 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003497 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003499 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003501 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003503 tty_insert_flip_char(tty, ch, status);
3504 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505 }
3506 } else {
3507 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003508 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 return;
3510 }
3511
3512stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003513 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 outb((EOSRR + portp->uartaddr), ioaddr);
3515 outb(0, (ioaddr + EREG_DATA));
3516}
3517
3518/*****************************************************************************/
3519
3520/*
3521 * Modem interrupt handler. The is called when the modem signal line
3522 * (DCD) has changed state. Leave most of the work to the off-level
3523 * processing routine.
3524 */
3525
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003526static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003528 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 unsigned int ioack;
3530 unsigned char misr;
3531
Jiri Slabya0564e12006-12-08 02:38:37 -08003532 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
3534 ioack = inb(ioaddr + EREG_MDACK);
3535 if (((ioack & panelp->ackmask) != 0) ||
3536 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3537 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3538 return;
3539 }
3540 portp = panelp->ports[(ioack >> 3)];
3541
3542 outb((MISR + portp->uartaddr), ioaddr);
3543 misr = inb(ioaddr + EREG_DATA);
3544 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003545 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 portp->stats.modem++;
3547 }
3548
3549 outb((EOSRR + portp->uartaddr), ioaddr);
3550 outb(0, (ioaddr + EREG_DATA));
3551}
3552
3553/*****************************************************************************/
3554/* SC26198 HARDWARE FUNCTIONS */
3555/*****************************************************************************/
3556
3557/*
3558 * These functions get/set/update the registers of the sc26198 UARTs.
3559 * Access to the sc26198 registers is via an address/data io port pair.
3560 * (Maybe should make this inline...)
3561 */
3562
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003563static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564{
3565 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003566 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567}
3568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003569static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570{
3571 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3572 outb(value, (portp->ioaddr + XP_DATA));
3573}
3574
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003575static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576{
3577 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3578 if (inb(portp->ioaddr + XP_DATA) != value) {
3579 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003580 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003582 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583}
3584
3585/*****************************************************************************/
3586
3587/*
3588 * Functions to get and set the sc26198 global registers.
3589 */
3590
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003591static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592{
3593 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003594 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595}
3596
3597#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003598static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599{
3600 outb(regnr, (portp->ioaddr + XP_ADDR));
3601 outb(value, (portp->ioaddr + XP_DATA));
3602}
3603#endif
3604
3605/*****************************************************************************/
3606
3607/*
3608 * Inbitialize the UARTs in a panel. We don't care what sort of board
3609 * these ports are on - since the port io registers are almost
3610 * identical when dealing with ports.
3611 */
3612
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003613static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614{
3615 int chipmask, i;
3616 int nrchips, ioaddr;
3617
Jiri Slabya0564e12006-12-08 02:38:37 -08003618 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
3620 BRDENABLE(panelp->brdnr, panelp->pagenr);
3621
3622/*
3623 * Check that each chip is present and started up OK.
3624 */
3625 chipmask = 0;
3626 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3627 if (brdp->brdtype == BRD_ECHPCI)
3628 outb(panelp->pagenr, brdp->ioctrl);
3629
Jiri Slabyc62429d2006-12-08 02:39:14 -08003630 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 ioaddr = panelp->iobase + (i * 4);
3632 outb(SCCR, (ioaddr + XP_ADDR));
3633 outb(CR_RESETALL, (ioaddr + XP_DATA));
3634 outb(TSTR, (ioaddr + XP_ADDR));
3635 if (inb(ioaddr + XP_DATA) != 0) {
3636 printk("STALLION: sc26198 not responding, "
3637 "brd=%d panel=%d chip=%d\n",
3638 panelp->brdnr, panelp->panelnr, i);
3639 continue;
3640 }
3641 chipmask |= (0x1 << i);
3642 outb(GCCR, (ioaddr + XP_ADDR));
3643 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3644 outb(WDTRCR, (ioaddr + XP_ADDR));
3645 outb(0xff, (ioaddr + XP_DATA));
3646 }
3647
3648 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003649 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650}
3651
3652/*****************************************************************************/
3653
3654/*
3655 * Initialize hardware specific port registers.
3656 */
3657
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003658static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659{
Jiri Slabya0564e12006-12-08 02:38:37 -08003660 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3661 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662
Jiri Slaby615e4a72006-12-08 02:38:38 -08003663 if ((brdp == NULL) || (panelp == NULL) ||
3664 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 return;
3666
3667 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3668 portp->uartaddr = (portp->portnr & 0x07) << 4;
3669 portp->pagenr = panelp->pagenr;
3670 portp->hwid = 0x1;
3671
3672 BRDENABLE(portp->brdnr, portp->pagenr);
3673 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3674 BRDDISABLE(portp->brdnr);
3675}
3676
3677/*****************************************************************************/
3678
3679/*
3680 * Set up the sc26198 registers for a port based on the termios port
3681 * settings.
3682 */
3683
Alan Cox606d0992006-12-08 02:38:45 -08003684static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003686 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 unsigned long flags;
3688 unsigned int baudrate;
3689 unsigned char mr0, mr1, mr2, clk;
3690 unsigned char imron, imroff, iopr, ipr;
3691
3692 mr0 = 0;
3693 mr1 = 0;
3694 mr2 = 0;
3695 clk = 0;
3696 iopr = 0;
3697 imron = 0;
3698 imroff = 0;
3699
3700 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003701 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 return;
3703
3704/*
3705 * Set up the RX char ignore mask with those RX error types we
3706 * can ignore.
3707 */
3708 portp->rxignoremsk = 0;
3709 if (tiosp->c_iflag & IGNPAR)
3710 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3711 SR_RXOVERRUN);
3712 if (tiosp->c_iflag & IGNBRK)
3713 portp->rxignoremsk |= SR_RXBREAK;
3714
3715 portp->rxmarkmsk = SR_RXOVERRUN;
3716 if (tiosp->c_iflag & (INPCK | PARMRK))
3717 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3718 if (tiosp->c_iflag & BRKINT)
3719 portp->rxmarkmsk |= SR_RXBREAK;
3720
3721/*
3722 * Go through the char size, parity and stop bits and set all the
3723 * option register appropriately.
3724 */
3725 switch (tiosp->c_cflag & CSIZE) {
3726 case CS5:
3727 mr1 |= MR1_CS5;
3728 break;
3729 case CS6:
3730 mr1 |= MR1_CS6;
3731 break;
3732 case CS7:
3733 mr1 |= MR1_CS7;
3734 break;
3735 default:
3736 mr1 |= MR1_CS8;
3737 break;
3738 }
3739
3740 if (tiosp->c_cflag & CSTOPB)
3741 mr2 |= MR2_STOP2;
3742 else
3743 mr2 |= MR2_STOP1;
3744
3745 if (tiosp->c_cflag & PARENB) {
3746 if (tiosp->c_cflag & PARODD)
3747 mr1 |= (MR1_PARENB | MR1_PARODD);
3748 else
3749 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003750 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
3753 mr1 |= MR1_ERRBLOCK;
3754
3755/*
3756 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3757 * space for hardware flow control and the like. This should be set to
3758 * VMIN.
3759 */
3760 mr2 |= MR2_RXFIFOHALF;
3761
3762/*
3763 * Calculate the baud rate timers. For now we will just assume that
3764 * the input and output baud are the same. The sc26198 has a fixed
3765 * baud rate table, so only discrete baud rates possible.
3766 */
3767 baudrate = tiosp->c_cflag & CBAUD;
3768 if (baudrate & CBAUDEX) {
3769 baudrate &= ~CBAUDEX;
3770 if ((baudrate < 1) || (baudrate > 4))
3771 tiosp->c_cflag &= ~CBAUDEX;
3772 else
3773 baudrate += 15;
3774 }
3775 baudrate = stl_baudrates[baudrate];
3776 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003777 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003779 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003781 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003783 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003785 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 baudrate = (portp->baud_base / portp->custom_divisor);
3787 }
3788 if (baudrate > STL_SC26198MAXBAUD)
3789 baudrate = STL_SC26198MAXBAUD;
3790
Jiri Slabyc62429d2006-12-08 02:39:14 -08003791 if (baudrate > 0)
3792 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 if (baudrate <= sc26198_baudtable[clk])
3794 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
3796/*
3797 * Check what form of modem signaling is required and set it up.
3798 */
3799 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003800 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 } else {
3802 iopr |= IOPR_DCDCOS;
3803 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003804 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 }
3806
3807/*
3808 * Setup sc26198 enhanced modes if we can. In particular we want to
3809 * handle as much of the flow control as possible automatically. As
3810 * well as saving a few CPU cycles it will also greatly improve flow
3811 * control reliability.
3812 */
3813 if (tiosp->c_iflag & IXON) {
3814 mr0 |= MR0_SWFTX | MR0_SWFT;
3815 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003816 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003818
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 if (tiosp->c_iflag & IXOFF)
3820 mr0 |= MR0_SWFRX;
3821
3822 if (tiosp->c_cflag & CRTSCTS) {
3823 mr2 |= MR2_AUTOCTS;
3824 mr1 |= MR1_AUTORTS;
3825 }
3826
3827/*
3828 * All sc26198 register values calculated so go through and set
3829 * them all up.
3830 */
3831
Jiri Slabya0564e12006-12-08 02:38:37 -08003832 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003834 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3835 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3836 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3838 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Alan Coxb65b5b52006-06-27 02:54:05 -07003840 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 BRDENABLE(portp->brdnr, portp->pagenr);
3842 stl_sc26198setreg(portp, IMR, 0);
3843 stl_sc26198updatereg(portp, MR0, mr0);
3844 stl_sc26198updatereg(portp, MR1, mr1);
3845 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3846 stl_sc26198updatereg(portp, MR2, mr2);
3847 stl_sc26198updatereg(portp, IOPIOR,
3848 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3849
3850 if (baudrate > 0) {
3851 stl_sc26198setreg(portp, TXCSR, clk);
3852 stl_sc26198setreg(portp, RXCSR, clk);
3853 }
3854
3855 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3856 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3857
3858 ipr = stl_sc26198getreg(portp, IPR);
3859 if (ipr & IPR_DCD)
3860 portp->sigs &= ~TIOCM_CD;
3861 else
3862 portp->sigs |= TIOCM_CD;
3863
3864 portp->imr = (portp->imr & ~imroff) | imron;
3865 stl_sc26198setreg(portp, IMR, portp->imr);
3866 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003867 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868}
3869
3870/*****************************************************************************/
3871
3872/*
3873 * Set the state of the DTR and RTS signals.
3874 */
3875
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003876static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877{
3878 unsigned char iopioron, iopioroff;
3879 unsigned long flags;
3880
Jiri Slabya0564e12006-12-08 02:38:37 -08003881 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3882 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883
3884 iopioron = 0;
3885 iopioroff = 0;
3886 if (dtr == 0)
3887 iopioroff |= IPR_DTR;
3888 else if (dtr > 0)
3889 iopioron |= IPR_DTR;
3890 if (rts == 0)
3891 iopioroff |= IPR_RTS;
3892 else if (rts > 0)
3893 iopioron |= IPR_RTS;
3894
Alan Coxb65b5b52006-06-27 02:54:05 -07003895 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 BRDENABLE(portp->brdnr, portp->pagenr);
3897 stl_sc26198setreg(portp, IOPIOR,
3898 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3899 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003900 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901}
3902
3903/*****************************************************************************/
3904
3905/*
3906 * Return the state of the signals.
3907 */
3908
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003909static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910{
3911 unsigned char ipr;
3912 unsigned long flags;
3913 int sigs;
3914
Jiri Slabya0564e12006-12-08 02:38:37 -08003915 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
Alan Coxb65b5b52006-06-27 02:54:05 -07003917 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 BRDENABLE(portp->brdnr, portp->pagenr);
3919 ipr = stl_sc26198getreg(portp, IPR);
3920 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003921 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923 sigs = 0;
3924 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3925 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3926 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3927 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3928 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003929 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930}
3931
3932/*****************************************************************************/
3933
3934/*
3935 * Enable/Disable the Transmitter and/or Receiver.
3936 */
3937
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003938static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939{
3940 unsigned char ccr;
3941 unsigned long flags;
3942
Jiri Slabya0564e12006-12-08 02:38:37 -08003943 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
3945 ccr = portp->crenable;
3946 if (tx == 0)
3947 ccr &= ~CR_TXENABLE;
3948 else if (tx > 0)
3949 ccr |= CR_TXENABLE;
3950 if (rx == 0)
3951 ccr &= ~CR_RXENABLE;
3952 else if (rx > 0)
3953 ccr |= CR_RXENABLE;
3954
Alan Coxb65b5b52006-06-27 02:54:05 -07003955 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 BRDENABLE(portp->brdnr, portp->pagenr);
3957 stl_sc26198setreg(portp, SCCR, ccr);
3958 BRDDISABLE(portp->brdnr);
3959 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003960 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961}
3962
3963/*****************************************************************************/
3964
3965/*
3966 * Start/stop the Transmitter and/or Receiver.
3967 */
3968
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003969static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970{
3971 unsigned char imr;
3972 unsigned long flags;
3973
Jiri Slabya0564e12006-12-08 02:38:37 -08003974 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
3976 imr = portp->imr;
3977 if (tx == 0)
3978 imr &= ~IR_TXRDY;
3979 else if (tx == 1)
3980 imr |= IR_TXRDY;
3981 if (rx == 0)
3982 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3983 else if (rx > 0)
3984 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3985
Alan Coxb65b5b52006-06-27 02:54:05 -07003986 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 BRDENABLE(portp->brdnr, portp->pagenr);
3988 stl_sc26198setreg(portp, IMR, imr);
3989 BRDDISABLE(portp->brdnr);
3990 portp->imr = imr;
3991 if (tx > 0)
3992 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003993 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994}
3995
3996/*****************************************************************************/
3997
3998/*
3999 * Disable all interrupts from this port.
4000 */
4001
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004002static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003{
4004 unsigned long flags;
4005
Jiri Slabya0564e12006-12-08 02:38:37 -08004006 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Alan Coxb65b5b52006-06-27 02:54:05 -07004008 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 BRDENABLE(portp->brdnr, portp->pagenr);
4010 portp->imr = 0;
4011 stl_sc26198setreg(portp, IMR, 0);
4012 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004013 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014}
4015
4016/*****************************************************************************/
4017
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004018static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019{
4020 unsigned long flags;
4021
Jiri Slabya0564e12006-12-08 02:38:37 -08004022 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023
Alan Coxb65b5b52006-06-27 02:54:05 -07004024 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 BRDENABLE(portp->brdnr, portp->pagenr);
4026 if (len == 1) {
4027 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4028 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004029 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004031
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004033 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034}
4035
4036/*****************************************************************************/
4037
4038/*
4039 * Take flow control actions...
4040 */
4041
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004042static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044 struct tty_struct *tty;
4045 unsigned long flags;
4046 unsigned char mr0;
4047
Jiri Slabya0564e12006-12-08 02:38:37 -08004048 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Jiri Slaby615e4a72006-12-08 02:38:38 -08004050 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004052 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004053 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 return;
4055
Alan Coxb65b5b52006-06-27 02:54:05 -07004056 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 BRDENABLE(portp->brdnr, portp->pagenr);
4058
4059 if (state) {
4060 if (tty->termios->c_iflag & IXOFF) {
4061 mr0 = stl_sc26198getreg(portp, MR0);
4062 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4063 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4064 mr0 |= MR0_SWFRX;
4065 portp->stats.rxxon++;
4066 stl_sc26198wait(portp);
4067 stl_sc26198setreg(portp, MR0, mr0);
4068 }
4069/*
4070 * Question: should we return RTS to what it was before? It may
4071 * have been set by an ioctl... Suppose not, since if you have
4072 * hardware flow control set then it is pretty silly to go and
4073 * set the RTS line by hand.
4074 */
4075 if (tty->termios->c_cflag & CRTSCTS) {
4076 stl_sc26198setreg(portp, MR1,
4077 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4078 stl_sc26198setreg(portp, IOPIOR,
4079 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4080 portp->stats.rxrtson++;
4081 }
4082 } else {
4083 if (tty->termios->c_iflag & IXOFF) {
4084 mr0 = stl_sc26198getreg(portp, MR0);
4085 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4086 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4087 mr0 &= ~MR0_SWFRX;
4088 portp->stats.rxxoff++;
4089 stl_sc26198wait(portp);
4090 stl_sc26198setreg(portp, MR0, mr0);
4091 }
4092 if (tty->termios->c_cflag & CRTSCTS) {
4093 stl_sc26198setreg(portp, MR1,
4094 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4095 stl_sc26198setreg(portp, IOPIOR,
4096 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4097 portp->stats.rxrtsoff++;
4098 }
4099 }
4100
4101 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004102 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004103 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104}
4105
4106/*****************************************************************************/
4107
4108/*
4109 * Send a flow control character.
4110 */
4111
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004112static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
4114 struct tty_struct *tty;
4115 unsigned long flags;
4116 unsigned char mr0;
4117
Jiri Slabya0564e12006-12-08 02:38:37 -08004118 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Jiri Slaby615e4a72006-12-08 02:38:38 -08004120 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004122 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004123 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 return;
4125
Alan Coxb65b5b52006-06-27 02:54:05 -07004126 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 BRDENABLE(portp->brdnr, portp->pagenr);
4128 if (state) {
4129 mr0 = stl_sc26198getreg(portp, MR0);
4130 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4131 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4132 mr0 |= MR0_SWFRX;
4133 portp->stats.rxxon++;
4134 stl_sc26198wait(portp);
4135 stl_sc26198setreg(portp, MR0, mr0);
4136 } else {
4137 mr0 = stl_sc26198getreg(portp, MR0);
4138 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4139 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4140 mr0 &= ~MR0_SWFRX;
4141 portp->stats.rxxoff++;
4142 stl_sc26198wait(portp);
4143 stl_sc26198setreg(portp, MR0, mr0);
4144 }
4145 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004146 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004147 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148}
4149
4150/*****************************************************************************/
4151
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004152static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153{
4154 unsigned long flags;
4155
Jiri Slabya0564e12006-12-08 02:38:37 -08004156 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157
Jiri Slaby615e4a72006-12-08 02:38:38 -08004158 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159 return;
4160
Alan Coxb65b5b52006-06-27 02:54:05 -07004161 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 BRDENABLE(portp->brdnr, portp->pagenr);
4163 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4164 stl_sc26198setreg(portp, SCCR, portp->crenable);
4165 BRDDISABLE(portp->brdnr);
4166 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004167 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168}
4169
4170/*****************************************************************************/
4171
4172/*
4173 * Return the current state of data flow on this port. This is only
4174 * really interresting when determining if data has fully completed
4175 * transmission or not... The sc26198 interrupt scheme cannot
4176 * determine when all data has actually drained, so we need to
4177 * check the port statusy register to be sure.
4178 */
4179
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004180static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181{
4182 unsigned long flags;
4183 unsigned char sr;
4184
Jiri Slabya0564e12006-12-08 02:38:37 -08004185 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
Jiri Slaby615e4a72006-12-08 02:38:38 -08004187 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004188 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004190 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191
Alan Coxb65b5b52006-06-27 02:54:05 -07004192 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 BRDENABLE(portp->brdnr, portp->pagenr);
4194 sr = stl_sc26198getreg(portp, SR);
4195 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004196 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Jesper Juhl014c2542006-01-15 02:37:08 +01004198 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199}
4200
4201/*****************************************************************************/
4202
4203/*
4204 * Delay for a small amount of time, to give the sc26198 a chance
4205 * to process a command...
4206 */
4207
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004208static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209{
4210 int i;
4211
Jiri Slabya0564e12006-12-08 02:38:37 -08004212 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213
Jiri Slaby615e4a72006-12-08 02:38:38 -08004214 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004215 return;
4216
Jiri Slabyc62429d2006-12-08 02:39:14 -08004217 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 stl_sc26198getglobreg(portp, TSTR);
4219}
4220
4221/*****************************************************************************/
4222
4223/*
4224 * If we are TX flow controlled and in IXANY mode then we may
4225 * need to unflow control here. We gotta do this because of the
4226 * automatic flow control modes of the sc26198.
4227 */
4228
Jiri Slaby60be4812006-12-08 02:38:40 -08004229static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
4231 unsigned char mr0;
4232
4233 mr0 = stl_sc26198getreg(portp, MR0);
4234 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4235 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4236 stl_sc26198wait(portp);
4237 stl_sc26198setreg(portp, MR0, mr0);
4238 clear_bit(ASYI_TXFLOWED, &portp->istate);
4239}
4240
4241/*****************************************************************************/
4242
4243/*
4244 * Interrupt service routine for sc26198 panels.
4245 */
4246
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004247static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004249 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 unsigned int iack;
4251
Alan Coxb65b5b52006-06-27 02:54:05 -07004252 spin_lock(&brd_lock);
4253
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254/*
4255 * Work around bug in sc26198 chip... Cannot have A6 address
4256 * line of UART high, else iack will be returned as 0.
4257 */
4258 outb(0, (iobase + 1));
4259
4260 iack = inb(iobase + XP_IACK);
4261 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4262
4263 if (iack & IVR_RXDATA)
4264 stl_sc26198rxisr(portp, iack);
4265 else if (iack & IVR_TXDATA)
4266 stl_sc26198txisr(portp);
4267 else
4268 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004269
4270 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
4273/*****************************************************************************/
4274
4275/*
4276 * Transmit interrupt handler. This has gotta be fast! Handling TX
4277 * chars is pretty simple, stuff as many as possible from the TX buffer
4278 * into the sc26198 FIFO.
4279 * In practice it is possible that interrupts are enabled but that the
4280 * port has been hung up. Need to handle not having any TX buffer here,
4281 * this is done by using the side effect that head and tail will also
4282 * be NULL if the buffer has been freed.
4283 */
4284
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004285static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286{
Alan Coxd18a7502008-10-13 10:40:07 +01004287 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 unsigned int ioaddr;
4289 unsigned char mr0;
4290 int len, stlen;
4291 char *head, *tail;
4292
Jiri Slabya0564e12006-12-08 02:38:37 -08004293 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294
4295 ioaddr = portp->ioaddr;
4296 head = portp->tx.head;
4297 tail = portp->tx.tail;
4298 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4299 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4300 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4301 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004302 tty = tty_port_tty_get(&portp->port);
4303 if (tty) {
4304 tty_wakeup(tty);
4305 tty_kref_put(tty);
4306 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 }
4308
4309 if (len == 0) {
4310 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4311 mr0 = inb(ioaddr + XP_DATA);
4312 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4313 portp->imr &= ~IR_TXRDY;
4314 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4315 outb(portp->imr, (ioaddr + XP_DATA));
4316 clear_bit(ASYI_TXBUSY, &portp->istate);
4317 } else {
4318 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4319 outb(mr0, (ioaddr + XP_DATA));
4320 }
4321 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004322 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004324 stlen = min_t(unsigned int, len,
4325 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 outb(GTXFIFO, (ioaddr + XP_ADDR));
4327 outsb((ioaddr + XP_DATA), tail, stlen);
4328 len -= stlen;
4329 tail += stlen;
4330 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4331 tail = portp->tx.buf;
4332 if (len > 0) {
4333 outsb((ioaddr + XP_DATA), tail, len);
4334 tail += len;
4335 }
4336 portp->tx.tail = tail;
4337 }
4338}
4339
4340/*****************************************************************************/
4341
4342/*
4343 * Receive character interrupt handler. Determine if we have good chars
4344 * or bad chars and then process appropriately. Good chars are easy
4345 * just shove the lot into the RX buffer and set all status byte to 0.
4346 * If a bad RX char then process as required. This routine needs to be
4347 * fast! In practice it is possible that we get an interrupt on a port
4348 * that is closed. This can happen on hangups - since they completely
4349 * shutdown a port not in user context. Need to handle this case.
4350 */
4351
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004352static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353{
4354 struct tty_struct *tty;
4355 unsigned int len, buflen, ioaddr;
4356
Jiri Slabya0564e12006-12-08 02:38:37 -08004357 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
Alan Coxd18a7502008-10-13 10:40:07 +01004359 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 ioaddr = portp->ioaddr;
4361 outb(GIBCR, (ioaddr + XP_ADDR));
4362 len = inb(ioaddr + XP_DATA) + 1;
4363
4364 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004365 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004366 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 outb(GRXFIFO, (ioaddr + XP_ADDR));
4368 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4369 portp->stats.rxlost += len;
4370 portp->stats.rxtotal += len;
4371 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004372 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004374 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004376 tty_prepare_flip_string(tty, &ptr, len);
4377 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 tty_schedule_flip(tty);
4379 portp->stats.rxtotal += len;
4380 }
4381 }
4382 } else {
4383 stl_sc26198rxbadchars(portp);
4384 }
4385
4386/*
4387 * If we are TX flow controlled and in IXANY mode then we may need
4388 * to unflow control here. We gotta do this because of the automatic
4389 * flow control modes of the sc26198.
4390 */
4391 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004392 if ((tty != NULL) &&
4393 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394 (tty->termios->c_iflag & IXANY)) {
4395 stl_sc26198txunflow(portp, tty);
4396 }
4397 }
Alan Coxd18a7502008-10-13 10:40:07 +01004398 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399}
4400
4401/*****************************************************************************/
4402
4403/*
4404 * Process an RX bad character.
4405 */
4406
Jiri Slaby60be4812006-12-08 02:38:40 -08004407static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408{
4409 struct tty_struct *tty;
4410 unsigned int ioaddr;
4411
Alan Coxd18a7502008-10-13 10:40:07 +01004412 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413 ioaddr = portp->ioaddr;
4414
4415 if (status & SR_RXPARITY)
4416 portp->stats.rxparity++;
4417 if (status & SR_RXFRAMING)
4418 portp->stats.rxframing++;
4419 if (status & SR_RXOVERRUN)
4420 portp->stats.rxoverrun++;
4421 if (status & SR_RXBREAK)
4422 portp->stats.rxbreaks++;
4423
Jiri Slaby615e4a72006-12-08 02:38:38 -08004424 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425 ((portp->rxignoremsk & status) == 0)) {
4426 if (portp->rxmarkmsk & status) {
4427 if (status & SR_RXBREAK) {
4428 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004429 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 do_SAK(tty);
4431 BRDENABLE(portp->brdnr, portp->pagenr);
4432 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004433 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004435 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004437 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004439 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004441 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Alan Cox33f0f882006-01-09 20:54:13 -08004444 tty_insert_flip_char(tty, ch, status);
4445 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
4447 if (status == 0)
4448 portp->stats.rxtotal++;
4449 }
Alan Coxd18a7502008-10-13 10:40:07 +01004450 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451}
4452
4453/*****************************************************************************/
4454
4455/*
4456 * Process all characters in the RX FIFO of the UART. Check all char
4457 * status bytes as well, and process as required. We need to check
4458 * all bytes in the FIFO, in case some more enter the FIFO while we
4459 * are here. To get the exact character error type we need to switch
4460 * into CHAR error mode (that is why we need to make sure we empty
4461 * the FIFO).
4462 */
4463
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004464static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465{
4466 unsigned char status, mr1;
4467 char ch;
4468
4469/*
4470 * To get the precise error type for each character we must switch
4471 * back into CHAR error mode.
4472 */
4473 mr1 = stl_sc26198getreg(portp, MR1);
4474 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4475
4476 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4477 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4478 ch = stl_sc26198getreg(portp, RXFIFO);
4479 stl_sc26198rxbadch(portp, status, ch);
4480 }
4481
4482/*
4483 * To get correct interrupt class we must switch back into BLOCK
4484 * error mode.
4485 */
4486 stl_sc26198setreg(portp, MR1, mr1);
4487}
4488
4489/*****************************************************************************/
4490
4491/*
4492 * Other interrupt handler. This includes modem signals, flow
4493 * control actions, etc. Most stuff is left to off-level interrupt
4494 * processing time.
4495 */
4496
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004497static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498{
4499 unsigned char cir, ipr, xisr;
4500
Jiri Slabya0564e12006-12-08 02:38:37 -08004501 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
4503 cir = stl_sc26198getglobreg(portp, CIR);
4504
4505 switch (cir & CIR_SUBTYPEMASK) {
4506 case CIR_SUBCOS:
4507 ipr = stl_sc26198getreg(portp, IPR);
4508 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004509 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 portp->stats.modem++;
4511 }
4512 break;
4513 case CIR_SUBXONXOFF:
4514 xisr = stl_sc26198getreg(portp, XISR);
4515 if (xisr & XISR_RXXONGOT) {
4516 set_bit(ASYI_TXFLOWED, &portp->istate);
4517 portp->stats.txxoff++;
4518 }
4519 if (xisr & XISR_RXXOFFGOT) {
4520 clear_bit(ASYI_TXFLOWED, &portp->istate);
4521 portp->stats.txxon++;
4522 }
4523 break;
4524 case CIR_SUBBREAK:
4525 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4526 stl_sc26198rxbadchars(portp);
4527 break;
4528 default:
4529 break;
4530 }
4531}
4532
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004533static void stl_free_isabrds(void)
4534{
4535 struct stlbrd *brdp;
4536 unsigned int i;
4537
4538 for (i = 0; i < stl_nrbrds; i++) {
4539 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4540 continue;
4541
4542 free_irq(brdp->irq, brdp);
4543
4544 stl_cleanup_panels(brdp);
4545
4546 release_region(brdp->ioaddr1, brdp->iosize1);
4547 if (brdp->iosize2 > 0)
4548 release_region(brdp->ioaddr2, brdp->iosize2);
4549
4550 kfree(brdp);
4551 stl_brds[i] = NULL;
4552 }
4553}
4554
Jiri Slaby23b85a12006-12-08 02:38:40 -08004555/*
4556 * Loadable module initialization stuff.
4557 */
4558static int __init stallion_module_init(void)
4559{
Jiri Slaby843b5682006-12-08 02:39:12 -08004560 struct stlbrd *brdp;
4561 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004562 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004563 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004564
4565 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4566
4567 spin_lock_init(&stallion_lock);
4568 spin_lock_init(&brd_lock);
4569
Jiri Slabye4151092007-06-08 13:46:52 -07004570 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4571 if (!stl_serial) {
4572 retval = -ENOMEM;
4573 goto err;
4574 }
4575
4576 stl_serial->owner = THIS_MODULE;
4577 stl_serial->driver_name = stl_drvname;
4578 stl_serial->name = "ttyE";
4579 stl_serial->major = STL_SERIALMAJOR;
4580 stl_serial->minor_start = 0;
4581 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4582 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4583 stl_serial->init_termios = stl_deftermios;
4584 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4585 tty_set_operations(stl_serial, &stl_ops);
4586
4587 retval = tty_register_driver(stl_serial);
4588 if (retval) {
4589 printk("STALLION: failed to register serial driver\n");
4590 goto err_frtty;
4591 }
4592
Jiri Slaby843b5682006-12-08 02:39:12 -08004593/*
4594 * Find any dynamically supported boards. That is via module load
4595 * line options.
4596 */
4597 for (i = stl_nrbrds; i < stl_nargs; i++) {
4598 memset(&conf, 0, sizeof(conf));
4599 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4600 continue;
4601 if ((brdp = stl_allocbrd()) == NULL)
4602 continue;
4603 brdp->brdnr = i;
4604 brdp->brdtype = conf.brdtype;
4605 brdp->ioaddr1 = conf.ioaddr1;
4606 brdp->ioaddr2 = conf.ioaddr2;
4607 brdp->irq = conf.irq;
4608 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004609 stl_brds[brdp->brdnr] = brdp;
4610 if (stl_brdinit(brdp)) {
4611 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004612 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004613 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004614 for (j = 0; j < brdp->nrports; j++)
4615 tty_register_device(stl_serial,
4616 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004617 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004618 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004619 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004620
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004621 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004622 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004623 if (retval && stl_nrbrds == 0) {
4624 printk(KERN_ERR "STALLION: can't register pci driver\n");
4625 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004626 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004627
4628/*
4629 * Set up a character driver for per board stuff. This is mainly used
4630 * to do stats ioctls on the ports.
4631 */
4632 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4633 printk("STALLION: failed to register serial board device\n");
4634
4635 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004636 if (IS_ERR(stallion_class))
4637 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004638 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004639 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4640 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004641
Jiri Slaby23b85a12006-12-08 02:38:40 -08004642 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004643err_unrtty:
4644 tty_unregister_driver(stl_serial);
4645err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004646 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004647err:
4648 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004649}
4650
4651static void __exit stallion_module_exit(void)
4652{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004653 struct stlbrd *brdp;
4654 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004655
4656 pr_debug("cleanup_module()\n");
4657
4658 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4659 stl_drvversion);
4660
4661/*
4662 * Free up all allocated resources used by the ports. This includes
4663 * memory and interrupts. As part of this process we will also do
4664 * a hangup on every open port - to try to flush out any processes
4665 * hanging onto ports.
4666 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004667 for (i = 0; i < stl_nrbrds; i++) {
4668 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4669 continue;
4670 for (j = 0; j < brdp->nrports; j++)
4671 tty_unregister_device(stl_serial,
4672 brdp->brdnr * STL_MAXPORTS + j);
4673 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004674
Jiri Slaby23b85a12006-12-08 02:38:40 -08004675 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004676 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004677 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004678 class_destroy(stallion_class);
4679
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004680 pci_unregister_driver(&stl_pcidriver);
4681
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004682 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004683
4684 tty_unregister_driver(stl_serial);
4685 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004686}
4687
4688module_init(stallion_module_init);
4689module_exit(stallion_module_exit);
4690
4691MODULE_AUTHOR("Greg Ungerer");
4692MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4693MODULE_LICENSE("GPL");