blob: 53e504f41b2043fa89b4b9a83637fe31251d38ab [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*****************************************************************************/
2
3/*
4 * stallion.c -- stallion multiport serial driver.
5 *
6 * Copyright (C) 1996-1999 Stallion Technologies
7 * Copyright (C) 1994-1996 Greg Ungerer.
8 *
9 * This code is loosely based on the Linux serial driver, written by
10 * Linus Torvalds, Theodore T'so and others.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27/*****************************************************************************/
28
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/tty_flip.h>
34#include <linux/serial.h>
Alexey Dobriyan8561c442009-03-31 15:19:18 -070035#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/cd1400.h>
37#include <linux/sc26198.h>
38#include <linux/comstats.h>
39#include <linux/stallion.h>
40#include <linux/ioport.h>
41#include <linux/init.h>
42#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/device.h>
44#include <linux/delay.h>
Jiri Slaby843b5682006-12-08 02:39:12 -080045#include <linux/ctype.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#include <asm/io.h>
48#include <asm/uaccess.h>
49
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <linux/pci.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52/*****************************************************************************/
53
54/*
55 * Define different board types. Use the standard Stallion "assigned"
56 * board numbers. Boards supported in this driver are abbreviated as
57 * EIO = EasyIO and ECH = EasyConnection 8/32.
58 */
59#define BRD_EASYIO 20
60#define BRD_ECH 21
61#define BRD_ECHMC 22
62#define BRD_ECHPCI 26
63#define BRD_ECH64PCI 27
64#define BRD_EASYIOPCI 28
65
Jiri Slaby843b5682006-12-08 02:39:12 -080066struct stlconf {
Jiri Slaby6b2c9452006-12-08 02:39:15 -080067 unsigned int brdtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 int ioaddr1;
69 int ioaddr2;
70 unsigned long memaddr;
71 int irq;
72 int irqtype;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
Jiri Slaby843b5682006-12-08 02:39:12 -080075static unsigned int stl_nrbrds;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77/*****************************************************************************/
78
79/*
80 * Define some important driver characteristics. Device major numbers
81 * allocated as per Linux Device Registry.
82 */
83#ifndef STL_SIOMEMMAJOR
84#define STL_SIOMEMMAJOR 28
85#endif
86#ifndef STL_SERIALMAJOR
87#define STL_SERIALMAJOR 24
88#endif
89#ifndef STL_CALLOUTMAJOR
90#define STL_CALLOUTMAJOR 25
91#endif
92
93/*
94 * Set the TX buffer size. Bigger is better, but we don't want
95 * to chew too much memory with buffers!
96 */
97#define STL_TXBUFLOW 512
98#define STL_TXBUFSIZE 4096
99
100/*****************************************************************************/
101
102/*
103 * Define our local driver identity first. Set up stuff to deal with
104 * all the local structures required by a serial tty driver.
105 */
106static char *stl_drvtitle = "Stallion Multiport Serial Driver";
107static char *stl_drvname = "stallion";
108static char *stl_drvversion = "5.6.0";
109
110static struct tty_driver *stl_serial;
111
112/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 * Define a local default termios struct. All ports will be created
114 * with this termios initially. Basically all it defines is a raw port
115 * at 9600, 8 data bits, 1 stop bit.
116 */
Alan Cox606d0992006-12-08 02:38:45 -0800117static struct ktermios stl_deftermios = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
119 .c_cc = INIT_C_CC,
Alan Cox606d0992006-12-08 02:38:45 -0800120 .c_ispeed = 9600,
121 .c_ospeed = 9600,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122};
123
124/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 * Define global place to put buffer overflow characters.
126 */
127static char stl_unwanted[SC26198_RXFIFOSIZE];
128
129/*****************************************************************************/
130
Jiri Slaby79cfe7a2006-12-08 02:39:14 -0800131static DEFINE_MUTEX(stl_brdslock);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800132static struct stlbrd *stl_brds[STL_MAXBRDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Alan Cox31f35932009-01-02 13:45:05 +0000134static const struct tty_port_operations stl_port_ops;
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136/*
137 * Per board state flags. Used with the state field of the board struct.
138 * Not really much here!
139 */
140#define BRD_FOUND 0x1
Jiri Slabyfc06b5c2006-12-08 02:39:13 -0800141#define STL_PROBED 0x2
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144/*
145 * Define the port structure istate flags. These set of flags are
146 * modified at interrupt time - so setting and reseting them needs
147 * to be atomic. Use the bit clear/setting routines for this.
148 */
149#define ASYI_TXBUSY 1
150#define ASYI_TXLOW 2
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800151#define ASYI_TXFLOWED 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153/*
154 * Define an array of board names as printable strings. Handy for
155 * referencing boards when printing trace and stuff.
156 */
157static char *stl_brdnames[] = {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800158 NULL,
159 NULL,
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 NULL,
165 NULL,
166 NULL,
167 NULL,
168 NULL,
169 NULL,
170 NULL,
171 NULL,
172 NULL,
173 NULL,
174 NULL,
175 NULL,
176 NULL,
177 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 "EasyIO",
179 "EC8/32-AT",
180 "EC8/32-MC",
Jiri Slaby615e4a72006-12-08 02:38:38 -0800181 NULL,
182 NULL,
183 NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 "EC8/32-PCI",
185 "EC8/64-PCI",
186 "EasyIO-PCI",
187};
188
189/*****************************************************************************/
190
191/*
192 * Define some string labels for arguments passed from the module
193 * load line. These allow for easy board definitions, and easy
194 * modification of the io, memory and irq resoucres.
195 */
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800196static unsigned int stl_nargs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197static char *board0[4];
198static char *board1[4];
199static char *board2[4];
200static char *board3[4];
201
202static char **stl_brdsp[] = {
203 (char **) &board0,
204 (char **) &board1,
205 (char **) &board2,
206 (char **) &board3
207};
208
209/*
210 * Define a set of common board names, and types. This is used to
211 * parse any module arguments.
212 */
213
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800214static struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 char *name;
216 int type;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800217} stl_brdstr[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 { "easyio", BRD_EASYIO },
219 { "eio", BRD_EASYIO },
220 { "20", BRD_EASYIO },
221 { "ec8/32", BRD_ECH },
222 { "ec8/32-at", BRD_ECH },
223 { "ec8/32-isa", BRD_ECH },
224 { "ech", BRD_ECH },
225 { "echat", BRD_ECH },
226 { "21", BRD_ECH },
227 { "ec8/32-mc", BRD_ECHMC },
228 { "ec8/32-mca", BRD_ECHMC },
229 { "echmc", BRD_ECHMC },
230 { "echmca", BRD_ECHMC },
231 { "22", BRD_ECHMC },
232 { "ec8/32-pc", BRD_ECHPCI },
233 { "ec8/32-pci", BRD_ECHPCI },
234 { "26", BRD_ECHPCI },
235 { "ec8/64-pc", BRD_ECH64PCI },
236 { "ec8/64-pci", BRD_ECH64PCI },
237 { "ech-pci", BRD_ECH64PCI },
238 { "echpci", BRD_ECH64PCI },
239 { "echpc", BRD_ECH64PCI },
240 { "27", BRD_ECH64PCI },
241 { "easyio-pc", BRD_EASYIOPCI },
242 { "easyio-pci", BRD_EASYIOPCI },
243 { "eio-pci", BRD_EASYIOPCI },
244 { "eiopci", BRD_EASYIOPCI },
245 { "28", BRD_EASYIOPCI },
246};
247
248/*
249 * Define the module agruments.
250 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252module_param_array(board0, charp, &stl_nargs, 0);
253MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
254module_param_array(board1, charp, &stl_nargs, 0);
255MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
256module_param_array(board2, charp, &stl_nargs, 0);
257MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
258module_param_array(board3, charp, &stl_nargs, 0);
259MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
260
261/*****************************************************************************/
262
263/*
264 * Hardware ID bits for the EasyIO and ECH boards. These defines apply
265 * to the directly accessible io ports of these boards (not the uarts -
266 * they are in cd1400.h and sc26198.h).
267 */
268#define EIO_8PORTRS 0x04
269#define EIO_4PORTRS 0x05
270#define EIO_8PORTDI 0x00
271#define EIO_8PORTM 0x06
272#define EIO_MK3 0x03
273#define EIO_IDBITMASK 0x07
274
275#define EIO_BRDMASK 0xf0
276#define ID_BRD4 0x10
277#define ID_BRD8 0x20
278#define ID_BRD16 0x30
279
280#define EIO_INTRPEND 0x08
281#define EIO_INTEDGE 0x00
282#define EIO_INTLEVEL 0x08
283#define EIO_0WS 0x10
284
285#define ECH_ID 0xa0
286#define ECH_IDBITMASK 0xe0
287#define ECH_BRDENABLE 0x08
288#define ECH_BRDDISABLE 0x00
289#define ECH_INTENABLE 0x01
290#define ECH_INTDISABLE 0x00
291#define ECH_INTLEVEL 0x02
292#define ECH_INTEDGE 0x00
293#define ECH_INTRPEND 0x01
294#define ECH_BRDRESET 0x01
295
296#define ECHMC_INTENABLE 0x01
297#define ECHMC_BRDRESET 0x02
298
299#define ECH_PNLSTATUS 2
300#define ECH_PNL16PORT 0x20
301#define ECH_PNLIDMASK 0x07
302#define ECH_PNLXPID 0x40
303#define ECH_PNLINTRPEND 0x80
304
305#define ECH_ADDR2MASK 0x1e0
306
307/*
308 * Define the vector mapping bits for the programmable interrupt board
309 * hardware. These bits encode the interrupt for the board to use - it
310 * is software selectable (except the EIO-8M).
311 */
312static unsigned char stl_vecmap[] = {
313 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
314 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
315};
316
317/*
Alan Coxb65b5b52006-06-27 02:54:05 -0700318 * Lock ordering is that you may not take stallion_lock holding
319 * brd_lock.
320 */
321
322static spinlock_t brd_lock; /* Guard the board mapping */
323static spinlock_t stallion_lock; /* Guard the tty driver */
324
325/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 * Set up enable and disable macros for the ECH boards. They require
327 * the secondary io address space to be activated and deactivated.
328 * This way all ECH boards can share their secondary io region.
329 * If this is an ECH-PCI board then also need to set the page pointer
330 * to point to the correct page.
331 */
332#define BRDENABLE(brdnr,pagenr) \
333 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
334 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE), \
335 stl_brds[(brdnr)]->ioctrl); \
336 else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
337 outb((pagenr), stl_brds[(brdnr)]->ioctrl);
338
339#define BRDDISABLE(brdnr) \
340 if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
341 outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE), \
342 stl_brds[(brdnr)]->ioctrl);
343
344#define STL_CD1400MAXBAUD 230400
345#define STL_SC26198MAXBAUD 460800
346
347#define STL_BAUDBASE 115200
348#define STL_CLOSEDELAY (5 * HZ / 10)
349
350/*****************************************************************************/
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352/*
353 * Define the Stallion PCI vendor and device IDs.
354 */
355#ifndef PCI_VENDOR_ID_STALLION
356#define PCI_VENDOR_ID_STALLION 0x124d
357#endif
358#ifndef PCI_DEVICE_ID_ECHPCI832
359#define PCI_DEVICE_ID_ECHPCI832 0x0000
360#endif
361#ifndef PCI_DEVICE_ID_ECHPCI864
362#define PCI_DEVICE_ID_ECHPCI864 0x0002
363#endif
364#ifndef PCI_DEVICE_ID_EIOPCI
365#define PCI_DEVICE_ID_EIOPCI 0x0003
366#endif
367
368/*
369 * Define structure to hold all Stallion PCI boards.
370 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800372static struct pci_device_id stl_pcibrds[] = {
373 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
374 .driver_data = BRD_ECH64PCI },
375 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
376 .driver_data = BRD_EASYIOPCI },
377 { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
378 .driver_data = BRD_ECHPCI },
379 { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
380 .driver_data = BRD_ECHPCI },
381 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382};
Jiri Slabyb1b84fe2006-12-08 02:39:09 -0800383MODULE_DEVICE_TABLE(pci, stl_pcibrds);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385/*****************************************************************************/
386
387/*
388 * Define macros to extract a brd/port number from a minor number.
389 */
390#define MINOR2BRD(min) (((min) & 0xc0) >> 6)
391#define MINOR2PORT(min) ((min) & 0x3f)
392
393/*
394 * Define a baud rate table that converts termios baud rate selector
395 * into the actual baud rate value. All baud rate calculations are
396 * based on the actual baud rate required.
397 */
398static unsigned int stl_baudrates[] = {
399 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
400 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
401};
402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403/*****************************************************************************/
404
405/*
406 * Declare all those functions in this driver!
407 */
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800410static int stl_brdinit(struct stlbrd *brdp);
Alan Coxd18a7502008-10-13 10:40:07 +0100411static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800412static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414/*
415 * CD1400 uart specific handling functions.
416 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800417static void stl_cd1400setreg(struct stlport *portp, int regnr, int value);
418static int stl_cd1400getreg(struct stlport *portp, int regnr);
419static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
420static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
421static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800422static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800423static int stl_cd1400getsignals(struct stlport *portp);
424static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
425static void stl_cd1400ccrwait(struct stlport *portp);
426static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
427static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
428static void stl_cd1400disableintrs(struct stlport *portp);
429static void stl_cd1400sendbreak(struct stlport *portp, int len);
430static void stl_cd1400flowctrl(struct stlport *portp, int state);
431static void stl_cd1400sendflow(struct stlport *portp, int state);
432static void stl_cd1400flush(struct stlport *portp);
433static int stl_cd1400datastate(struct stlport *portp);
434static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
435static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
436static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
437static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
438static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800440static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
442/*
443 * SC26198 uart specific handling functions.
444 */
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800445static void stl_sc26198setreg(struct stlport *portp, int regnr, int value);
446static int stl_sc26198getreg(struct stlport *portp, int regnr);
447static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
448static int stl_sc26198getglobreg(struct stlport *portp, int regnr);
449static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
450static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800451static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800452static int stl_sc26198getsignals(struct stlport *portp);
453static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
454static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
455static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
456static void stl_sc26198disableintrs(struct stlport *portp);
457static void stl_sc26198sendbreak(struct stlport *portp, int len);
458static void stl_sc26198flowctrl(struct stlport *portp, int state);
459static void stl_sc26198sendflow(struct stlport *portp, int state);
460static void stl_sc26198flush(struct stlport *portp);
461static int stl_sc26198datastate(struct stlport *portp);
462static void stl_sc26198wait(struct stlport *portp);
463static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
464static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
465static void stl_sc26198txisr(struct stlport *port);
466static void stl_sc26198rxisr(struct stlport *port, unsigned int iack);
467static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
468static void stl_sc26198rxbadchars(struct stlport *portp);
469static void stl_sc26198otherisr(struct stlport *port, unsigned int iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471/*****************************************************************************/
472
473/*
474 * Generic UART support structure.
475 */
476typedef struct uart {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800477 int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
478 void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
Alan Cox606d0992006-12-08 02:38:45 -0800479 void (*setport)(struct stlport *portp, struct ktermios *tiosp);
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800480 int (*getsignals)(struct stlport *portp);
481 void (*setsignals)(struct stlport *portp, int dtr, int rts);
482 void (*enablerxtx)(struct stlport *portp, int rx, int tx);
483 void (*startrxtx)(struct stlport *portp, int rx, int tx);
484 void (*disableintrs)(struct stlport *portp);
485 void (*sendbreak)(struct stlport *portp, int len);
486 void (*flowctrl)(struct stlport *portp, int state);
487 void (*sendflow)(struct stlport *portp, int state);
488 void (*flush)(struct stlport *portp);
489 int (*datastate)(struct stlport *portp);
490 void (*intr)(struct stlpanel *panelp, unsigned int iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491} uart_t;
492
493/*
494 * Define some macros to make calling these functions nice and clean.
495 */
496#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit)
497#define stl_portinit (* ((uart_t *) portp->uartp)->portinit)
498#define stl_setport (* ((uart_t *) portp->uartp)->setport)
499#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals)
500#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals)
501#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx)
502#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx)
503#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs)
504#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak)
505#define stl_flowctrl (* ((uart_t *) portp->uartp)->flowctrl)
506#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow)
507#define stl_flush (* ((uart_t *) portp->uartp)->flush)
508#define stl_datastate (* ((uart_t *) portp->uartp)->datastate)
509
510/*****************************************************************************/
511
512/*
513 * CD1400 UART specific data initialization.
514 */
515static uart_t stl_cd1400uart = {
516 stl_cd1400panelinit,
517 stl_cd1400portinit,
518 stl_cd1400setport,
519 stl_cd1400getsignals,
520 stl_cd1400setsignals,
521 stl_cd1400enablerxtx,
522 stl_cd1400startrxtx,
523 stl_cd1400disableintrs,
524 stl_cd1400sendbreak,
525 stl_cd1400flowctrl,
526 stl_cd1400sendflow,
527 stl_cd1400flush,
528 stl_cd1400datastate,
529 stl_cd1400eiointr
530};
531
532/*
533 * Define the offsets within the register bank of a cd1400 based panel.
534 * These io address offsets are common to the EasyIO board as well.
535 */
536#define EREG_ADDR 0
537#define EREG_DATA 4
538#define EREG_RXACK 5
539#define EREG_TXACK 6
540#define EREG_MDACK 7
541
542#define EREG_BANKSIZE 8
543
544#define CD1400_CLK 25000000
545#define CD1400_CLK8M 20000000
546
547/*
548 * Define the cd1400 baud rate clocks. These are used when calculating
549 * what clock and divisor to use for the required baud rate. Also
550 * define the maximum baud rate allowed, and the default base baud.
551 */
552static int stl_cd1400clkdivs[] = {
553 CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
554};
555
556/*****************************************************************************/
557
558/*
559 * SC26198 UART specific data initization.
560 */
561static uart_t stl_sc26198uart = {
562 stl_sc26198panelinit,
563 stl_sc26198portinit,
564 stl_sc26198setport,
565 stl_sc26198getsignals,
566 stl_sc26198setsignals,
567 stl_sc26198enablerxtx,
568 stl_sc26198startrxtx,
569 stl_sc26198disableintrs,
570 stl_sc26198sendbreak,
571 stl_sc26198flowctrl,
572 stl_sc26198sendflow,
573 stl_sc26198flush,
574 stl_sc26198datastate,
575 stl_sc26198intr
576};
577
578/*
579 * Define the offsets within the register bank of a sc26198 based panel.
580 */
581#define XP_DATA 0
582#define XP_ADDR 1
583#define XP_MODID 2
584#define XP_STATUS 2
585#define XP_IACK 3
586
587#define XP_BANKSIZE 4
588
589/*
590 * Define the sc26198 baud rate table. Offsets within the table
591 * represent the actual baud rate selector of sc26198 registers.
592 */
593static unsigned int sc26198_baudtable[] = {
594 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
595 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
596 230400, 460800, 921600
597};
598
Tobias Klauserfe971072006-01-09 20:54:02 -0800599#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601/*****************************************************************************/
602
603/*
604 * Define the driver info for a user level control device. Used mainly
605 * to get at port stats - only not using the port device itself.
606 */
Arjan van de Ven62322d22006-07-03 00:24:21 -0700607static const struct file_operations stl_fsiomem = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 .owner = THIS_MODULE,
609 .ioctl = stl_memioctl,
610};
611
gregkh@suse.deca8eca62005-03-23 09:53:09 -0800612static struct class *stallion_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800614static void stl_cd_change(struct stlport *portp)
615{
616 unsigned int oldsigs = portp->sigs;
Alan Coxd18a7502008-10-13 10:40:07 +0100617 struct tty_struct *tty = tty_port_tty_get(&portp->port);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800618
Alan Coxd18a7502008-10-13 10:40:07 +0100619 if (!tty)
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800620 return;
621
622 portp->sigs = stl_getsignals(portp);
623
624 if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100625 wake_up_interruptible(&portp->port.open_wait);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800626
627 if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
Alan Coxf8ae4762008-07-16 21:56:37 +0100628 if (portp->port.flags & ASYNC_CHECK_CD)
Alan Coxd18a7502008-10-13 10:40:07 +0100629 tty_hangup(tty);
630 tty_kref_put(tty);
Jiri Slabyccfea3c2008-02-07 00:16:39 -0800631}
632
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 * Check for any arguments passed in on the module load command line.
635 */
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637/*****************************************************************************/
638
639/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 * Parse the supplied argument string, into the board conf struct.
641 */
642
Jiri Slaby40e82652006-12-08 02:38:41 -0800643static int __init stl_parsebrd(struct stlconf *confp, char **argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 char *sp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800646 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Jiri Slabya0564e12006-12-08 02:38:37 -0800648 pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Jiri Slaby615e4a72006-12-08 02:38:38 -0800650 if ((argp[0] == NULL) || (*argp[0] == 0))
Jesper Juhl014c2542006-01-15 02:37:08 +0100651 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Jiri Slabyc62429d2006-12-08 02:39:14 -0800653 for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
Jiri Slaby843b5682006-12-08 02:39:12 -0800654 *sp = tolower(*sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Jiri Slabyc62429d2006-12-08 02:39:14 -0800656 for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
658 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -0800659
Tobias Klauserfe971072006-01-09 20:54:02 -0800660 if (i == ARRAY_SIZE(stl_brdstr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 printk("STALLION: unknown board name, %s?\n", argp[0]);
Tobias Klauserfe971072006-01-09 20:54:02 -0800662 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
664
665 confp->brdtype = stl_brdstr[i].type;
666
667 i = 1;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800668 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800669 confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 i++;
671 if (confp->brdtype == BRD_ECH) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800672 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800673 confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 i++;
675 }
Jiri Slaby615e4a72006-12-08 02:38:38 -0800676 if ((argp[i] != NULL) && (*argp[i] != 0))
Jiri Slaby843b5682006-12-08 02:39:12 -0800677 confp->irq = simple_strtoul(argp[i], NULL, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100678 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}
680
681/*****************************************************************************/
682
683/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 * Allocate a new board structure. Fill out the basic info in it.
685 */
686
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800687static struct stlbrd *stl_allocbrd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800689 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800691 brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800692 if (!brdp) {
Alan Coxb65b5b52006-06-27 02:54:05 -0700693 printk("STALLION: failed to allocate memory (size=%Zd)\n",
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800694 sizeof(struct stlbrd));
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800695 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 brdp->magic = STL_BOARDMAGIC;
Jesper Juhl014c2542006-01-15 02:37:08 +0100699 return brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700}
701
702/*****************************************************************************/
703
704static int stl_open(struct tty_struct *tty, struct file *filp)
705{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800706 struct stlport *portp;
707 struct stlbrd *brdp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000708 struct tty_port *port;
Jiri Slaby6b2c9452006-12-08 02:39:15 -0800709 unsigned int minordev, brdnr, panelnr;
Alan Cox4350f3f2009-01-02 13:46:24 +0000710 int portnr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Jiri Slabya0564e12006-12-08 02:38:37 -0800712 pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
714 minordev = tty->index;
715 brdnr = MINOR2BRD(minordev);
716 if (brdnr >= stl_nrbrds)
Jesper Juhl014c2542006-01-15 02:37:08 +0100717 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800719 if (brdp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100720 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 minordev = MINOR2PORT(minordev);
Jiri Slabyc62429d2006-12-08 02:39:14 -0800723 for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
Jiri Slaby615e4a72006-12-08 02:38:38 -0800724 if (brdp->panels[panelnr] == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 break;
726 if (minordev < brdp->panels[panelnr]->nrports) {
727 portnr = minordev;
728 break;
729 }
730 minordev -= brdp->panels[panelnr]->nrports;
731 }
732 if (portnr < 0)
Jesper Juhl014c2542006-01-15 02:37:08 +0100733 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735 portp = brdp->panels[panelnr]->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -0800736 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100737 return -ENODEV;
Alan Cox4350f3f2009-01-02 13:46:24 +0000738 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740/*
741 * On the first open of the device setup the port hardware, and
742 * initialize the per port data structure.
743 */
Alan Cox4350f3f2009-01-02 13:46:24 +0000744 tty_port_tty_set(port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 tty->driver_data = portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000746 port->count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Alan Cox4350f3f2009-01-02 13:46:24 +0000748 if ((port->flags & ASYNC_INITIALIZED) == 0) {
Tobias Klauserb0b4ed72006-03-31 02:30:56 -0800749 if (!portp->tx.buf) {
750 portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
751 if (!portp->tx.buf)
Jesper Juhl014c2542006-01-15 02:37:08 +0100752 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 portp->tx.head = portp->tx.buf;
754 portp->tx.tail = portp->tx.buf;
755 }
756 stl_setport(portp, tty->termios);
757 portp->sigs = stl_getsignals(portp);
758 stl_setsignals(portp, 1, 1);
759 stl_enablerxtx(portp, 1, 1);
760 stl_startrxtx(portp, 1, 0);
761 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox4350f3f2009-01-02 13:46:24 +0000762 port->flags |= ASYNC_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
Alan Cox4350f3f2009-01-02 13:46:24 +0000764 return tty_port_block_til_ready(port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765}
766
767/*****************************************************************************/
768
Alan Cox31f35932009-01-02 13:45:05 +0000769static int stl_carrier_raised(struct tty_port *port)
770{
771 struct stlport *portp = container_of(port, struct stlport, port);
772 return (portp->sigs & TIOCM_CD) ? 1 : 0;
773}
774
Alan Coxfcc8ac12009-06-11 12:24:17 +0100775static void stl_dtr_rts(struct tty_port *port, int on)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Alan Cox4350f3f2009-01-02 13:46:24 +0000777 struct stlport *portp = container_of(port, struct stlport, port);
778 /* Takes brd_lock internally */
Alan Coxfcc8ac12009-06-11 12:24:17 +0100779 stl_setsignals(portp, on, on);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780}
781
782/*****************************************************************************/
783
Jiri Slaby96b066b2006-12-08 02:38:42 -0800784static void stl_flushbuffer(struct tty_struct *tty)
785{
786 struct stlport *portp;
787
788 pr_debug("stl_flushbuffer(tty=%p)\n", tty);
789
Jiri Slaby96b066b2006-12-08 02:38:42 -0800790 portp = tty->driver_data;
791 if (portp == NULL)
792 return;
793
794 stl_flush(portp);
795 tty_wakeup(tty);
796}
797
798/*****************************************************************************/
799
800static void stl_waituntilsent(struct tty_struct *tty, int timeout)
801{
802 struct stlport *portp;
803 unsigned long tend;
804
805 pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
806
Jiri Slaby96b066b2006-12-08 02:38:42 -0800807 portp = tty->driver_data;
808 if (portp == NULL)
809 return;
810
811 if (timeout == 0)
812 timeout = HZ;
813 tend = jiffies + timeout;
814
Alan Cox978e5952008-04-30 00:53:59 -0700815 lock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800816 while (stl_datastate(portp)) {
817 if (signal_pending(current))
818 break;
819 msleep_interruptible(20);
820 if (time_after_eq(jiffies, tend))
821 break;
822 }
Alan Cox978e5952008-04-30 00:53:59 -0700823 unlock_kernel();
Jiri Slaby96b066b2006-12-08 02:38:42 -0800824}
825
826/*****************************************************************************/
827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828static void stl_close(struct tty_struct *tty, struct file *filp)
829{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800830 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +0000831 struct tty_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 unsigned long flags;
833
Jiri Slabya0564e12006-12-08 02:38:37 -0800834 pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
836 portp = tty->driver_data;
Alan Coxa6614992009-01-02 13:46:50 +0000837 BUG_ON(portp == NULL);
838
Alan Cox4350f3f2009-01-02 13:46:24 +0000839 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Alan Coxa6614992009-01-02 13:46:50 +0000841 if (tty_port_close_start(port, tty, filp) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843/*
844 * May want to wait for any data to drain before closing. The BUSY
845 * flag keeps track of whether we are still sending or not - it is
846 * very accurate for the cd1400, not quite so for the sc26198.
847 * (The sc26198 has no "end-of-data" interrupt only empty FIFO)
848 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 stl_waituntilsent(tty, (HZ / 2));
850
Alan Cox4350f3f2009-01-02 13:46:24 +0000851 spin_lock_irqsave(&port->lock, flags);
Alan Coxf8ae4762008-07-16 21:56:37 +0100852 portp->port.flags &= ~ASYNC_INITIALIZED;
Alan Cox4350f3f2009-01-02 13:46:24 +0000853 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxb65b5b52006-06-27 02:54:05 -0700854
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 stl_disableintrs(portp);
856 if (tty->termios->c_cflag & HUPCL)
857 stl_setsignals(portp, 0, 0);
858 stl_enablerxtx(portp, 0, 0);
859 stl_flushbuffer(tty);
860 portp->istate = 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800861 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -0800863 portp->tx.buf = NULL;
864 portp->tx.head = NULL;
865 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Alan Coxa6614992009-01-02 13:46:50 +0000868 tty_port_close_end(port, tty);
Alan Cox4350f3f2009-01-02 13:46:24 +0000869 tty_port_tty_set(port, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870}
871
872/*****************************************************************************/
873
874/*
875 * Write routine. Take data and stuff it in to the TX ring queue.
876 * If transmit interrupts are not running then start them.
877 */
878
879static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
880{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800881 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 unsigned int len, stlen;
883 unsigned char *chbuf;
884 char *head, *tail;
885
Jiri Slabya0564e12006-12-08 02:38:37 -0800886 pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800889 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100890 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800891 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100892 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893
894/*
895 * If copying direct from user space we must cater for page faults,
896 * causing us to "sleep" here for a while. To handle this copy in all
897 * the data we need now, into a local buffer. Then when we got it all
898 * copy it into the TX buffer.
899 */
900 chbuf = (unsigned char *) buf;
901
902 head = portp->tx.head;
903 tail = portp->tx.tail;
904 if (head >= tail) {
905 len = STL_TXBUFSIZE - (head - tail) - 1;
906 stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
907 } else {
908 len = tail - head - 1;
909 stlen = len;
910 }
911
Jiri Slaby843b5682006-12-08 02:39:12 -0800912 len = min(len, (unsigned int)count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 count = 0;
914 while (len > 0) {
Jiri Slaby843b5682006-12-08 02:39:12 -0800915 stlen = min(len, stlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 memcpy(head, chbuf, stlen);
917 len -= stlen;
918 chbuf += stlen;
919 count += stlen;
920 head += stlen;
921 if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
922 head = portp->tx.buf;
923 stlen = tail - head;
924 }
925 }
926 portp->tx.head = head;
927
928 clear_bit(ASYI_TXLOW, &portp->istate);
929 stl_startrxtx(portp, -1, 1);
930
Jesper Juhl014c2542006-01-15 02:37:08 +0100931 return count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932}
933
934/*****************************************************************************/
935
David Howells4a561222008-07-22 11:18:43 +0100936static int stl_putchar(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800938 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 unsigned int len;
940 char *head, *tail;
941
Jiri Slabya0564e12006-12-08 02:38:37 -0800942 pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800945 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +0100946 return -EINVAL;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800947 if (portp->tx.buf == NULL)
David Howells4a561222008-07-22 11:18:43 +0100948 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
950 head = portp->tx.head;
951 tail = portp->tx.tail;
952
953 len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
954 len--;
955
956 if (len > 0) {
957 *head++ = ch;
958 if (head >= (portp->tx.buf + STL_TXBUFSIZE))
959 head = portp->tx.buf;
960 }
961 portp->tx.head = head;
David Howells4a561222008-07-22 11:18:43 +0100962 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963}
964
965/*****************************************************************************/
966
967/*
968 * If there are any characters in the buffer then make sure that TX
969 * interrupts are on and get'em out. Normally used after the putchar
970 * routine has been called.
971 */
972
973static void stl_flushchars(struct tty_struct *tty)
974{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800975 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
Jiri Slabya0564e12006-12-08 02:38:37 -0800977 pr_debug("stl_flushchars(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800980 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 return;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800982 if (portp->tx.buf == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 return;
984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 stl_startrxtx(portp, -1, 1);
986}
987
988/*****************************************************************************/
989
990static int stl_writeroom(struct tty_struct *tty)
991{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -0800992 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 char *head, *tail;
994
Jiri Slabya0564e12006-12-08 02:38:37 -0800995 pr_debug("stl_writeroom(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -0800998 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +0100999 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001000 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001001 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003 head = portp->tx.head;
1004 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001005 return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006}
1007
1008/*****************************************************************************/
1009
1010/*
1011 * Return number of chars in the TX buffer. Normally we would just
1012 * calculate the number of chars in the buffer and return that, but if
1013 * the buffer is empty and TX interrupts are still on then we return
1014 * that the buffer still has 1 char in it. This way whoever called us
1015 * will not think that ALL chars have drained - since the UART still
1016 * must have some chars in it (we are busy after all).
1017 */
1018
1019static int stl_charsinbuffer(struct tty_struct *tty)
1020{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001021 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 unsigned int size;
1023 char *head, *tail;
1024
Jiri Slabya0564e12006-12-08 02:38:37 -08001025 pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001028 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001029 return 0;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001030 if (portp->tx.buf == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001031 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
1033 head = portp->tx.head;
1034 tail = portp->tx.tail;
1035 size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
1036 if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
1037 size = 1;
Jesper Juhl014c2542006-01-15 02:37:08 +01001038 return size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039}
1040
1041/*****************************************************************************/
1042
1043/*
1044 * Generate the serial struct info.
1045 */
1046
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001047static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048{
1049 struct serial_struct sio;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001050 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Jiri Slabya0564e12006-12-08 02:38:37 -08001052 pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 memset(&sio, 0, sizeof(struct serial_struct));
1055 sio.line = portp->portnr;
1056 sio.port = portp->ioaddr;
Alan Coxf8ae4762008-07-16 21:56:37 +01001057 sio.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 sio.baud_base = portp->baud_base;
1059 sio.close_delay = portp->close_delay;
1060 sio.closing_wait = portp->closing_wait;
1061 sio.custom_divisor = portp->custom_divisor;
1062 sio.hub6 = 0;
1063 if (portp->uartp == &stl_cd1400uart) {
1064 sio.type = PORT_CIRRUS;
1065 sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
1066 } else {
1067 sio.type = PORT_UNKNOWN;
1068 sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
1069 }
1070
1071 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001072 if (brdp != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 sio.irq = brdp->irq;
1074
1075 return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
1076}
1077
1078/*****************************************************************************/
1079
1080/*
1081 * Set port according to the serial struct info.
1082 * At this point we do not do any auto-configure stuff, so we will
1083 * just quietly ignore any requests to change irq, etc.
1084 */
1085
Alan Coxd18a7502008-10-13 10:40:07 +01001086static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087{
Alan Coxd18a7502008-10-13 10:40:07 +01001088 struct stlport * portp = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 struct serial_struct sio;
1090
Jiri Slabya0564e12006-12-08 02:38:37 -08001091 pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
1094 return -EFAULT;
1095 if (!capable(CAP_SYS_ADMIN)) {
1096 if ((sio.baud_base != portp->baud_base) ||
1097 (sio.close_delay != portp->close_delay) ||
1098 ((sio.flags & ~ASYNC_USR_MASK) !=
Alan Coxf8ae4762008-07-16 21:56:37 +01001099 (portp->port.flags & ~ASYNC_USR_MASK)))
Jesper Juhl014c2542006-01-15 02:37:08 +01001100 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 }
1102
Alan Coxf8ae4762008-07-16 21:56:37 +01001103 portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 (sio.flags & ASYNC_USR_MASK);
1105 portp->baud_base = sio.baud_base;
1106 portp->close_delay = sio.close_delay;
1107 portp->closing_wait = sio.closing_wait;
1108 portp->custom_divisor = sio.custom_divisor;
Alan Coxd18a7502008-10-13 10:40:07 +01001109 stl_setport(portp, tty->termios);
Jesper Juhl014c2542006-01-15 02:37:08 +01001110 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111}
1112
1113/*****************************************************************************/
1114
1115static int stl_tiocmget(struct tty_struct *tty, struct file *file)
1116{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001117 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001120 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001121 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001123 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
1125 return stl_getsignals(portp);
1126}
1127
1128static int stl_tiocmset(struct tty_struct *tty, struct file *file,
1129 unsigned int set, unsigned int clear)
1130{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001131 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 int rts = -1, dtr = -1;
1133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001135 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001136 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001138 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
1140 if (set & TIOCM_RTS)
1141 rts = 1;
1142 if (set & TIOCM_DTR)
1143 dtr = 1;
1144 if (clear & TIOCM_RTS)
1145 rts = 0;
1146 if (clear & TIOCM_DTR)
1147 dtr = 0;
1148
1149 stl_setsignals(portp, dtr, rts);
1150 return 0;
1151}
1152
1153static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
1154{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001155 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 int rc;
1157 void __user *argp = (void __user *)arg;
1158
Jiri Slabya0564e12006-12-08 02:38:37 -08001159 pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
1160 arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001163 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01001164 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
Jiri Slabyc62429d2006-12-08 02:39:14 -08001167 (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 if (tty->flags & (1 << TTY_IO_ERROR))
Jesper Juhl014c2542006-01-15 02:37:08 +01001169 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171 rc = 0;
1172
Alan Coxf433c652008-04-30 00:53:23 -07001173 lock_kernel();
1174
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 case TIOCGSERIAL:
1177 rc = stl_getserial(portp, argp);
1178 break;
1179 case TIOCSSERIAL:
Alan Coxd18a7502008-10-13 10:40:07 +01001180 rc = stl_setserial(tty, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 break;
1182 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01001183 rc = stl_getportstats(tty, portp, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 break;
1185 case COM_CLRPORTSTATS:
1186 rc = stl_clrportstats(portp, argp);
1187 break;
1188 case TIOCSERCONFIG:
1189 case TIOCSERGWILD:
1190 case TIOCSERSWILD:
1191 case TIOCSERGETLSR:
1192 case TIOCSERGSTRUCT:
1193 case TIOCSERGETMULTI:
1194 case TIOCSERSETMULTI:
1195 default:
1196 rc = -ENOIOCTLCMD;
1197 break;
1198 }
Alan Coxf433c652008-04-30 00:53:23 -07001199 unlock_kernel();
Jesper Juhl014c2542006-01-15 02:37:08 +01001200 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
1203/*****************************************************************************/
1204
Jiri Slaby96b066b2006-12-08 02:38:42 -08001205/*
1206 * Start the transmitter again. Just turn TX interrupts back on.
1207 */
1208
1209static void stl_start(struct tty_struct *tty)
1210{
1211 struct stlport *portp;
1212
1213 pr_debug("stl_start(tty=%p)\n", tty);
1214
Jiri Slaby96b066b2006-12-08 02:38:42 -08001215 portp = tty->driver_data;
1216 if (portp == NULL)
1217 return;
1218 stl_startrxtx(portp, -1, 1);
1219}
1220
1221/*****************************************************************************/
1222
Alan Cox606d0992006-12-08 02:38:45 -08001223static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001225 struct stlport *portp;
Alan Cox606d0992006-12-08 02:38:45 -08001226 struct ktermios *tiosp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Jiri Slabya0564e12006-12-08 02:38:37 -08001228 pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001231 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 return;
1233
1234 tiosp = tty->termios;
1235 if ((tiosp->c_cflag == old->c_cflag) &&
1236 (tiosp->c_iflag == old->c_iflag))
1237 return;
1238
1239 stl_setport(portp, tiosp);
1240 stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
1241 -1);
1242 if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
1243 tty->hw_stopped = 0;
1244 stl_start(tty);
1245 }
1246 if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
Alan Coxf8ae4762008-07-16 21:56:37 +01001247 wake_up_interruptible(&portp->port.open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248}
1249
1250/*****************************************************************************/
1251
1252/*
1253 * Attempt to flow control who ever is sending us data. Based on termios
1254 * settings use software or/and hardware flow control.
1255 */
1256
1257static void stl_throttle(struct tty_struct *tty)
1258{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001259 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Jiri Slabya0564e12006-12-08 02:38:37 -08001261 pr_debug("stl_throttle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001264 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 return;
1266 stl_flowctrl(portp, 0);
1267}
1268
1269/*****************************************************************************/
1270
1271/*
1272 * Unflow control the device sending us data...
1273 */
1274
1275static void stl_unthrottle(struct tty_struct *tty)
1276{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001277 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Jiri Slabya0564e12006-12-08 02:38:37 -08001279 pr_debug("stl_unthrottle(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001282 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return;
1284 stl_flowctrl(portp, 1);
1285}
1286
1287/*****************************************************************************/
1288
1289/*
1290 * Stop the transmitter. Basically to do this we will just turn TX
1291 * interrupts off.
1292 */
1293
1294static void stl_stop(struct tty_struct *tty)
1295{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001296 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Jiri Slabya0564e12006-12-08 02:38:37 -08001298 pr_debug("stl_stop(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001301 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return;
1303 stl_startrxtx(portp, -1, 0);
1304}
1305
1306/*****************************************************************************/
1307
1308/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 * Hangup this port. This is pretty much like closing the port, only
1310 * a little more brutal. No waiting for data to drain. Shutdown the
1311 * port and maybe drop signals.
1312 */
1313
1314static void stl_hangup(struct tty_struct *tty)
1315{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001316 struct stlport *portp;
Alan Cox4350f3f2009-01-02 13:46:24 +00001317 struct tty_port *port;
1318 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Jiri Slabya0564e12006-12-08 02:38:37 -08001320 pr_debug("stl_hangup(tty=%p)\n", tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001323 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 return;
Alan Cox4350f3f2009-01-02 13:46:24 +00001325 port = &portp->port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Alan Cox4350f3f2009-01-02 13:46:24 +00001327 spin_lock_irqsave(&port->lock, flags);
1328 port->flags &= ~ASYNC_INITIALIZED;
1329 spin_unlock_irqrestore(&port->lock, flags);
1330
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 stl_disableintrs(portp);
1332 if (tty->termios->c_cflag & HUPCL)
1333 stl_setsignals(portp, 0, 0);
1334 stl_enablerxtx(portp, 0, 0);
1335 stl_flushbuffer(tty);
1336 portp->istate = 0;
1337 set_bit(TTY_IO_ERROR, &tty->flags);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001338 if (portp->tx.buf != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 kfree(portp->tx.buf);
Jiri Slaby615e4a72006-12-08 02:38:38 -08001340 portp->tx.buf = NULL;
1341 portp->tx.head = NULL;
1342 portp->tx.tail = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
Alan Cox4350f3f2009-01-02 13:46:24 +00001344 tty_port_hangup(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345}
1346
1347/*****************************************************************************/
1348
David Howells4a561222008-07-22 11:18:43 +01001349static int stl_breakctl(struct tty_struct *tty, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001351 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Jiri Slabya0564e12006-12-08 02:38:37 -08001353 pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001356 if (portp == NULL)
David Howells4a561222008-07-22 11:18:43 +01001357 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
1359 stl_sendbreak(portp, ((state == -1) ? 1 : 2));
David Howells4a561222008-07-22 11:18:43 +01001360 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
1363/*****************************************************************************/
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365static void stl_sendxchar(struct tty_struct *tty, char ch)
1366{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001367 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Jiri Slabya0564e12006-12-08 02:38:37 -08001369 pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 portp = tty->driver_data;
Jiri Slaby615e4a72006-12-08 02:38:38 -08001372 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 return;
1374
1375 if (ch == STOP_CHAR(tty))
1376 stl_sendflow(portp, 0);
1377 else if (ch == START_CHAR(tty))
1378 stl_sendflow(portp, 1);
1379 else
1380 stl_putchar(tty, ch);
1381}
1382
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001383static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384{
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001385 int sigs;
1386 char sep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001388 seq_printf(m, "%d: uart:%s tx:%d rx:%d",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
1390 (int) portp->stats.txtotal, (int) portp->stats.rxtotal);
1391
1392 if (portp->stats.rxframing)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001393 seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 if (portp->stats.rxparity)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001395 seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 if (portp->stats.rxbreaks)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001397 seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 if (portp->stats.rxoverrun)
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001399 seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 sigs = stl_getsignals(portp);
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001402 sep = ' ';
1403 if (sigs & TIOCM_RTS) {
1404 seq_printf(m, "%c%s", sep, "RTS");
1405 sep = '|';
1406 }
1407 if (sigs & TIOCM_CTS) {
1408 seq_printf(m, "%c%s", sep, "CTS");
1409 sep = '|';
1410 }
1411 if (sigs & TIOCM_DTR) {
1412 seq_printf(m, "%c%s", sep, "DTR");
1413 sep = '|';
1414 }
1415 if (sigs & TIOCM_CD) {
1416 seq_printf(m, "%c%s", sep, "DCD");
1417 sep = '|';
1418 }
1419 if (sigs & TIOCM_DSR) {
1420 seq_printf(m, "%c%s", sep, "DSR");
1421 sep = '|';
1422 }
1423 seq_putc(m, '\n');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424}
1425
1426/*****************************************************************************/
1427
1428/*
1429 * Port info, read from the /proc file system.
1430 */
1431
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001432static int stl_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001434 struct stlbrd *brdp;
1435 struct stlpanel *panelp;
1436 struct stlport *portp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001437 unsigned int brdnr, panelnr, portnr;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001438 int totalport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 totalport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001442 seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444/*
1445 * We scan through for each board, panel and port. The offset is
1446 * calculated on the fly, and irrelevant ports are skipped.
1447 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001448 for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001450 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 continue;
1452 if (brdp->state == 0)
1453 continue;
1454
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 totalport = brdnr * STL_MAXPORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001456 for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001458 if (panelp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 continue;
1460
Jiri Slabyc62429d2006-12-08 02:39:14 -08001461 for (portnr = 0; portnr < panelp->nrports; portnr++,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 totalport++) {
1463 portp = panelp->ports[portnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08001464 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 continue;
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001466 stl_portinfo(m, portp, totalport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 }
1468 }
1469 }
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001470 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471}
1472
Alexey Dobriyan8561c442009-03-31 15:19:18 -07001473static int stl_proc_open(struct inode *inode, struct file *file)
1474{
1475 return single_open(file, stl_proc_show, NULL);
1476}
1477
1478static const struct file_operations stl_proc_fops = {
1479 .owner = THIS_MODULE,
1480 .open = stl_proc_open,
1481 .read = seq_read,
1482 .llseek = seq_lseek,
1483 .release = single_release,
1484};
1485
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486/*****************************************************************************/
1487
1488/*
1489 * All board interrupts are vectored through here first. This code then
1490 * calls off to the approrpriate board interrupt handlers.
1491 */
1492
David Howells7d12e782006-10-05 14:55:46 +01001493static irqreturn_t stl_intr(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001495 struct stlbrd *brdp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
Jeff Garzika6f97b22007-10-31 05:20:49 -04001497 pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
1499 return IRQ_RETVAL((* brdp->isr)(brdp));
1500}
1501
1502/*****************************************************************************/
1503
1504/*
1505 * Interrupt service routine for EasyIO board types.
1506 */
1507
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001508static int stl_eiointr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001510 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 unsigned int iobase;
1512 int handled = 0;
1513
Alan Coxb65b5b52006-06-27 02:54:05 -07001514 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 panelp = brdp->panels[0];
1516 iobase = panelp->iobase;
1517 while (inb(brdp->iostatus) & EIO_INTRPEND) {
1518 handled = 1;
1519 (* panelp->isr)(panelp, iobase);
1520 }
Alan Coxb65b5b52006-06-27 02:54:05 -07001521 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 return handled;
1523}
1524
1525/*****************************************************************************/
1526
1527/*
1528 * Interrupt service routine for ECH-AT board types.
1529 */
1530
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001531static int stl_echatintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001533 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001534 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 int handled = 0;
1536
1537 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1538
1539 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1540 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001541 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 ioaddr = brdp->bnkstataddr[bnknr];
1543 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1544 panelp = brdp->bnk2panel[bnknr];
1545 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1546 }
1547 }
1548 }
1549
1550 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
1551
1552 return handled;
1553}
1554
1555/*****************************************************************************/
1556
1557/*
1558 * Interrupt service routine for ECH-MCA board types.
1559 */
1560
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001561static int stl_echmcaintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001563 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001564 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 int handled = 0;
1566
1567 while (inb(brdp->iostatus) & ECH_INTRPEND) {
1568 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001569 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 ioaddr = brdp->bnkstataddr[bnknr];
1571 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1572 panelp = brdp->bnk2panel[bnknr];
1573 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1574 }
1575 }
1576 }
1577 return handled;
1578}
1579
1580/*****************************************************************************/
1581
1582/*
1583 * Interrupt service routine for ECH-PCI board types.
1584 */
1585
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001586static int stl_echpciintr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001588 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001589 unsigned int ioaddr, bnknr, recheck;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 int handled = 0;
1591
1592 while (1) {
1593 recheck = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001594 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
1596 ioaddr = brdp->bnkstataddr[bnknr];
1597 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1598 panelp = brdp->bnk2panel[bnknr];
1599 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1600 recheck++;
1601 handled = 1;
1602 }
1603 }
1604 if (! recheck)
1605 break;
1606 }
1607 return handled;
1608}
1609
1610/*****************************************************************************/
1611
1612/*
1613 * Interrupt service routine for ECH-8/64-PCI board types.
1614 */
1615
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001616static int stl_echpci64intr(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001618 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001619 unsigned int ioaddr, bnknr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 int handled = 0;
1621
1622 while (inb(brdp->ioctrl) & 0x1) {
1623 handled = 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08001624 for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 ioaddr = brdp->bnkstataddr[bnknr];
1626 if (inb(ioaddr) & ECH_PNLINTRPEND) {
1627 panelp = brdp->bnk2panel[bnknr];
1628 (* panelp->isr)(panelp, (ioaddr & 0xfffc));
1629 }
1630 }
1631 }
1632
1633 return handled;
1634}
1635
1636/*****************************************************************************/
1637
1638/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 * Initialize all the ports on a panel.
1640 */
1641
Jiri Slaby705c1862006-12-08 02:39:11 -08001642static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001644 struct stlport *portp;
1645 unsigned int i;
1646 int chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647
Jiri Slabya0564e12006-12-08 02:38:37 -08001648 pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
1650 chipmask = stl_panelinit(brdp, panelp);
1651
1652/*
1653 * All UART's are initialized (if found!). Now go through and setup
1654 * each ports data structures.
1655 */
Jiri Slabyc62429d2006-12-08 02:39:14 -08001656 for (i = 0; i < panelp->nrports; i++) {
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001657 portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001658 if (!portp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001660 "(size=%Zd)\n", sizeof(struct stlport));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 break;
1662 }
Alan Coxd18a7502008-10-13 10:40:07 +01001663 tty_port_init(&portp->port);
Alan Cox31f35932009-01-02 13:45:05 +00001664 portp->port.ops = &stl_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 portp->magic = STL_PORTMAGIC;
1666 portp->portnr = i;
1667 portp->brdnr = panelp->brdnr;
1668 portp->panelnr = panelp->panelnr;
1669 portp->uartp = panelp->uartp;
1670 portp->clk = brdp->clk;
1671 portp->baud_base = STL_BAUDBASE;
1672 portp->close_delay = STL_CLOSEDELAY;
1673 portp->closing_wait = 30 * HZ;
Alan Coxf8ae4762008-07-16 21:56:37 +01001674 init_waitqueue_head(&portp->port.open_wait);
1675 init_waitqueue_head(&portp->port.close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 portp->stats.brd = portp->brdnr;
1677 portp->stats.panel = portp->panelnr;
1678 portp->stats.port = portp->portnr;
1679 panelp->ports[i] = portp;
1680 stl_portinit(brdp, panelp, portp);
1681 }
1682
Jiri Slabyc62429d2006-12-08 02:39:14 -08001683 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684}
1685
Jiri Slaby3b85b342006-12-08 02:39:10 -08001686static void stl_cleanup_panels(struct stlbrd *brdp)
1687{
1688 struct stlpanel *panelp;
1689 struct stlport *portp;
1690 unsigned int j, k;
Alan Coxd18a7502008-10-13 10:40:07 +01001691 struct tty_struct *tty;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001692
1693 for (j = 0; j < STL_MAXPANELS; j++) {
1694 panelp = brdp->panels[j];
1695 if (panelp == NULL)
1696 continue;
1697 for (k = 0; k < STL_PORTSPERPANEL; k++) {
1698 portp = panelp->ports[k];
1699 if (portp == NULL)
1700 continue;
Alan Coxd18a7502008-10-13 10:40:07 +01001701 tty = tty_port_tty_get(&portp->port);
1702 if (tty != NULL) {
1703 stl_hangup(tty);
1704 tty_kref_put(tty);
1705 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001706 kfree(portp->tx.buf);
1707 kfree(portp);
1708 }
1709 kfree(panelp);
1710 }
1711}
1712
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713/*****************************************************************************/
1714
1715/*
1716 * Try to find and initialize an EasyIO board.
1717 */
1718
Jiri Slaby705c1862006-12-08 02:39:11 -08001719static int __devinit stl_initeio(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001721 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 unsigned int status;
1723 char *name;
Jiri Slaby3b85b342006-12-08 02:39:10 -08001724 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Jiri Slabya0564e12006-12-08 02:38:37 -08001726 pr_debug("stl_initeio(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
1728 brdp->ioctrl = brdp->ioaddr1 + 1;
1729 brdp->iostatus = brdp->ioaddr1 + 2;
1730
1731 status = inb(brdp->iostatus);
1732 if ((status & EIO_IDBITMASK) == EIO_MK3)
1733 brdp->ioctrl++;
1734
1735/*
1736 * Handle board specific stuff now. The real difference is PCI
1737 * or not PCI.
1738 */
1739 if (brdp->brdtype == BRD_EASYIOPCI) {
1740 brdp->iosize1 = 0x80;
1741 brdp->iosize2 = 0x80;
1742 name = "serial(EIO-PCI)";
1743 outb(0x41, (brdp->ioaddr2 + 0x4c));
1744 } else {
1745 brdp->iosize1 = 8;
1746 name = "serial(EIO)";
1747 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1748 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1749 printk("STALLION: invalid irq=%d for brd=%d\n",
1750 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001751 retval = -EINVAL;
1752 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 }
1754 outb((stl_vecmap[brdp->irq] | EIO_0WS |
1755 ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
1756 brdp->ioctrl);
1757 }
1758
Jiri Slaby3b85b342006-12-08 02:39:10 -08001759 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1761 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1762 "%x conflicts with another device\n", brdp->brdnr,
1763 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001764 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 }
1766
1767 if (brdp->iosize2 > 0)
1768 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1769 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1770 "address %x conflicts with another device\n",
1771 brdp->brdnr, brdp->ioaddr2);
1772 printk(KERN_WARNING "STALLION: Warning, also "
1773 "releasing board %d I/O address %x \n",
1774 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001775 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 }
1777
1778/*
1779 * Everything looks OK, so let's go ahead and probe for the hardware.
1780 */
1781 brdp->clk = CD1400_CLK;
1782 brdp->isr = stl_eiointr;
1783
Jiri Slaby3b85b342006-12-08 02:39:10 -08001784 retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 switch (status & EIO_IDBITMASK) {
1786 case EIO_8PORTM:
1787 brdp->clk = CD1400_CLK8M;
1788 /* fall thru */
1789 case EIO_8PORTRS:
1790 case EIO_8PORTDI:
1791 brdp->nrports = 8;
1792 break;
1793 case EIO_4PORTRS:
1794 brdp->nrports = 4;
1795 break;
1796 case EIO_MK3:
1797 switch (status & EIO_BRDMASK) {
1798 case ID_BRD4:
1799 brdp->nrports = 4;
1800 break;
1801 case ID_BRD8:
1802 brdp->nrports = 8;
1803 break;
1804 case ID_BRD16:
1805 brdp->nrports = 16;
1806 break;
1807 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001808 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 }
1810 break;
1811 default:
Jiri Slaby3b85b342006-12-08 02:39:10 -08001812 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 }
1814
1815/*
1816 * We have verified that the board is actually present, so now we
1817 * can complete the setup.
1818 */
1819
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001820 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08001821 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 printk(KERN_WARNING "STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001823 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby3b85b342006-12-08 02:39:10 -08001824 retval = -ENOMEM;
1825 goto err_rel2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 panelp->magic = STL_PANELMAGIC;
1829 panelp->brdnr = brdp->brdnr;
1830 panelp->panelnr = 0;
1831 panelp->nrports = brdp->nrports;
1832 panelp->iobase = brdp->ioaddr1;
1833 panelp->hwid = status;
1834 if ((status & EIO_IDBITMASK) == EIO_MK3) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001835 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 panelp->isr = stl_sc26198intr;
1837 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08001838 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 panelp->isr = stl_cd1400eiointr;
1840 }
1841
1842 brdp->panels[0] = panelp;
1843 brdp->nrpanels = 1;
1844 brdp->state |= BRD_FOUND;
1845 brdp->hwid = status;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07001846 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 printk("STALLION: failed to register interrupt "
1848 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001849 retval = -ENODEV;
1850 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 }
Jiri Slaby3b85b342006-12-08 02:39:10 -08001852
1853 return 0;
1854err_fr:
1855 stl_cleanup_panels(brdp);
1856err_rel2:
1857 if (brdp->iosize2 > 0)
1858 release_region(brdp->ioaddr2, brdp->iosize2);
1859err_rel1:
1860 release_region(brdp->ioaddr1, brdp->iosize1);
1861err:
1862 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863}
1864
1865/*****************************************************************************/
1866
1867/*
1868 * Try to find an ECH board and initialize it. This code is capable of
1869 * dealing with all types of ECH board.
1870 */
1871
Jiri Slaby705c1862006-12-08 02:39:11 -08001872static int __devinit stl_initech(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08001874 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08001875 unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i;
1876 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 char *name;
1878
Jiri Slabya0564e12006-12-08 02:38:37 -08001879 pr_debug("stl_initech(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
1881 status = 0;
1882 conflict = 0;
1883
1884/*
1885 * Set up the initial board register contents for boards. This varies a
1886 * bit between the different board types. So we need to handle each
1887 * separately. Also do a check that the supplied IRQ is good.
1888 */
1889 switch (brdp->brdtype) {
1890
1891 case BRD_ECH:
1892 brdp->isr = stl_echatintr;
1893 brdp->ioctrl = brdp->ioaddr1 + 1;
1894 brdp->iostatus = brdp->ioaddr1 + 1;
1895 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001896 if ((status & ECH_IDBITMASK) != ECH_ID) {
1897 retval = -ENODEV;
1898 goto err;
1899 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1901 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1902 printk("STALLION: invalid irq=%d for brd=%d\n",
1903 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001904 retval = -EINVAL;
1905 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 }
1907 status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
1908 status |= (stl_vecmap[brdp->irq] << 1);
1909 outb((status | ECH_BRDRESET), brdp->ioaddr1);
1910 brdp->ioctrlval = ECH_INTENABLE |
1911 ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
Jiri Slabyc62429d2006-12-08 02:39:14 -08001912 for (i = 0; i < 10; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
1914 brdp->iosize1 = 2;
1915 brdp->iosize2 = 32;
1916 name = "serial(EC8/32)";
1917 outb(status, brdp->ioaddr1);
1918 break;
1919
1920 case BRD_ECHMC:
1921 brdp->isr = stl_echmcaintr;
1922 brdp->ioctrl = brdp->ioaddr1 + 0x20;
1923 brdp->iostatus = brdp->ioctrl;
1924 status = inb(brdp->iostatus);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001925 if ((status & ECH_IDBITMASK) != ECH_ID) {
1926 retval = -ENODEV;
1927 goto err;
1928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 if ((brdp->irq < 0) || (brdp->irq > 15) ||
1930 (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
1931 printk("STALLION: invalid irq=%d for brd=%d\n",
1932 brdp->irq, brdp->brdnr);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001933 retval = -EINVAL;
1934 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 }
1936 outb(ECHMC_BRDRESET, brdp->ioctrl);
1937 outb(ECHMC_INTENABLE, brdp->ioctrl);
1938 brdp->iosize1 = 64;
1939 name = "serial(EC8/32-MC)";
1940 break;
1941
1942 case BRD_ECHPCI:
1943 brdp->isr = stl_echpciintr;
1944 brdp->ioctrl = brdp->ioaddr1 + 2;
1945 brdp->iosize1 = 4;
1946 brdp->iosize2 = 8;
1947 name = "serial(EC8/32-PCI)";
1948 break;
1949
1950 case BRD_ECH64PCI:
1951 brdp->isr = stl_echpci64intr;
1952 brdp->ioctrl = brdp->ioaddr2 + 0x40;
1953 outb(0x43, (brdp->ioaddr1 + 0x4c));
1954 brdp->iosize1 = 0x80;
1955 brdp->iosize2 = 0x80;
1956 name = "serial(EC8/64-PCI)";
1957 break;
1958
1959 default:
1960 printk("STALLION: unknown board type=%d\n", brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001961 retval = -EINVAL;
1962 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 }
1964
1965/*
1966 * Check boards for possible IO address conflicts and return fail status
1967 * if an IO conflict found.
1968 */
Jiri Slaby3b85b342006-12-08 02:39:10 -08001969 retval = -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
1971 printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
1972 "%x conflicts with another device\n", brdp->brdnr,
1973 brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001974 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 }
1976
1977 if (brdp->iosize2 > 0)
1978 if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
1979 printk(KERN_WARNING "STALLION: Warning, board %d I/O "
1980 "address %x conflicts with another device\n",
1981 brdp->brdnr, brdp->ioaddr2);
1982 printk(KERN_WARNING "STALLION: Warning, also "
1983 "releasing board %d I/O address %x \n",
1984 brdp->brdnr, brdp->ioaddr1);
Jiri Slaby3b85b342006-12-08 02:39:10 -08001985 goto err_rel1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 }
1987
1988/*
1989 * Scan through the secondary io address space looking for panels.
1990 * As we find'em allocate and initialize panel structures for each.
1991 */
1992 brdp->clk = CD1400_CLK;
1993 brdp->hwid = status;
1994
1995 ioaddr = brdp->ioaddr2;
1996 banknr = 0;
1997 panelnr = 0;
1998 nxtid = 0;
1999
Jiri Slabyc62429d2006-12-08 02:39:14 -08002000 for (i = 0; i < STL_MAXPANELS; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 if (brdp->brdtype == BRD_ECHPCI) {
2002 outb(nxtid, brdp->ioctrl);
2003 ioaddr = brdp->ioaddr2;
2004 }
2005 status = inb(ioaddr + ECH_PNLSTATUS);
2006 if ((status & ECH_PNLIDMASK) != nxtid)
Jiri Slaby64834b22007-06-08 13:46:52 -07002007 break;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002008 panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
Tobias Klauserb0b4ed72006-03-31 02:30:56 -08002009 if (!panelp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 printk("STALLION: failed to allocate memory "
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002011 "(size=%Zd)\n", sizeof(struct stlpanel));
Jiri Slaby49277b12007-06-08 13:46:53 -07002012 retval = -ENOMEM;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002013 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 panelp->magic = STL_PANELMAGIC;
2016 panelp->brdnr = brdp->brdnr;
2017 panelp->panelnr = panelnr;
2018 panelp->iobase = ioaddr;
2019 panelp->pagenr = nxtid;
2020 panelp->hwid = status;
2021 brdp->bnk2panel[banknr] = panelp;
2022 brdp->bnkpageaddr[banknr] = nxtid;
2023 brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
2024
2025 if (status & ECH_PNLXPID) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002026 panelp->uartp = &stl_sc26198uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 panelp->isr = stl_sc26198intr;
2028 if (status & ECH_PNL16PORT) {
2029 panelp->nrports = 16;
2030 brdp->bnk2panel[banknr] = panelp;
2031 brdp->bnkpageaddr[banknr] = nxtid;
2032 brdp->bnkstataddr[banknr++] = ioaddr + 4 +
2033 ECH_PNLSTATUS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002034 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 panelp->nrports = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 } else {
Jiri Slaby615e4a72006-12-08 02:38:38 -08002037 panelp->uartp = &stl_cd1400uart;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038 panelp->isr = stl_cd1400echintr;
2039 if (status & ECH_PNL16PORT) {
2040 panelp->nrports = 16;
2041 panelp->ackmask = 0x80;
2042 if (brdp->brdtype != BRD_ECHPCI)
2043 ioaddr += EREG_BANKSIZE;
2044 brdp->bnk2panel[banknr] = panelp;
2045 brdp->bnkpageaddr[banknr] = ++nxtid;
2046 brdp->bnkstataddr[banknr++] = ioaddr +
2047 ECH_PNLSTATUS;
2048 } else {
2049 panelp->nrports = 8;
2050 panelp->ackmask = 0xc0;
2051 }
2052 }
2053
2054 nxtid++;
2055 ioaddr += EREG_BANKSIZE;
2056 brdp->nrports += panelp->nrports;
2057 brdp->panels[panelnr++] = panelp;
2058 if ((brdp->brdtype != BRD_ECHPCI) &&
Jiri Slaby49277b12007-06-08 13:46:53 -07002059 (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
2060 retval = -EINVAL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002061 goto err_fr;
Jiri Slaby49277b12007-06-08 13:46:53 -07002062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 }
2064
2065 brdp->nrpanels = panelnr;
2066 brdp->nrbnks = banknr;
2067 if (brdp->brdtype == BRD_ECH)
2068 outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
2069
2070 brdp->state |= BRD_FOUND;
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -07002071 if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 printk("STALLION: failed to register interrupt "
2073 "routine for %s irq=%d\n", name, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002074 retval = -ENODEV;
2075 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 }
2077
Jiri Slaby3b85b342006-12-08 02:39:10 -08002078 return 0;
2079err_fr:
2080 stl_cleanup_panels(brdp);
2081 if (brdp->iosize2 > 0)
2082 release_region(brdp->ioaddr2, brdp->iosize2);
2083err_rel1:
2084 release_region(brdp->ioaddr1, brdp->iosize1);
2085err:
2086 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087}
2088
2089/*****************************************************************************/
2090
2091/*
2092 * Initialize and configure the specified board.
2093 * Scan through all the boards in the configuration and see what we
2094 * can find. Handle EIO and the ECH boards a little differently here
2095 * since the initial search and setup is very different.
2096 */
2097
Jiri Slaby705c1862006-12-08 02:39:11 -08002098static int __devinit stl_brdinit(struct stlbrd *brdp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099{
Jiri Slaby3b85b342006-12-08 02:39:10 -08002100 int i, retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Jiri Slabya0564e12006-12-08 02:38:37 -08002102 pr_debug("stl_brdinit(brdp=%p)\n", brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
2104 switch (brdp->brdtype) {
2105 case BRD_EASYIO:
2106 case BRD_EASYIOPCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002107 retval = stl_initeio(brdp);
2108 if (retval)
2109 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 break;
2111 case BRD_ECH:
2112 case BRD_ECHMC:
2113 case BRD_ECHPCI:
2114 case BRD_ECH64PCI:
Jiri Slaby3b85b342006-12-08 02:39:10 -08002115 retval = stl_initech(brdp);
2116 if (retval)
2117 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 break;
2119 default:
2120 printk("STALLION: board=%d is unknown board type=%d\n",
2121 brdp->brdnr, brdp->brdtype);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002122 retval = -ENODEV;
2123 goto err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 if ((brdp->state & BRD_FOUND) == 0) {
2127 printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
2128 stl_brdnames[brdp->brdtype], brdp->brdnr,
2129 brdp->ioaddr1, brdp->irq);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002130 goto err_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 }
2132
Jiri Slabyc62429d2006-12-08 02:39:14 -08002133 for (i = 0; i < STL_MAXPANELS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002134 if (brdp->panels[i] != NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135 stl_initports(brdp, brdp->panels[i]);
2136
2137 printk("STALLION: %s found, board=%d io=%x irq=%d "
2138 "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
2139 brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
2140 brdp->nrports);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002141
2142 return 0;
2143err_free:
2144 free_irq(brdp->irq, brdp);
2145
2146 stl_cleanup_panels(brdp);
2147
2148 release_region(brdp->ioaddr1, brdp->iosize1);
2149 if (brdp->iosize2 > 0)
2150 release_region(brdp->ioaddr2, brdp->iosize2);
Jiri Slaby3b85b342006-12-08 02:39:10 -08002151err:
2152 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
2155/*****************************************************************************/
2156
2157/*
2158 * Find the next available board number that is free.
2159 */
2160
Jiri Slaby705c1862006-12-08 02:39:11 -08002161static int __devinit stl_getbrdnr(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002163 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164
Jiri Slabyc62429d2006-12-08 02:39:14 -08002165 for (i = 0; i < STL_MAXBRDS; i++)
Jiri Slaby615e4a72006-12-08 02:38:38 -08002166 if (stl_brds[i] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 if (i >= stl_nrbrds)
2168 stl_nrbrds = i + 1;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002169 return i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08002171
2172 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173}
2174
2175/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176/*
2177 * We have a Stallion board. Allocate a board structure and
2178 * initialize it. Read its IO and IRQ resources from PCI
2179 * configuration space.
2180 */
2181
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002182static int __devinit stl_pciprobe(struct pci_dev *pdev,
2183 const struct pci_device_id *ent)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002185 struct stlbrd *brdp;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002186 unsigned int i, brdtype = ent->driver_data;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002187 int brdnr, retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002189 if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
Jiri Slaby3b85b342006-12-08 02:39:10 -08002190 goto err;
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002191
Jiri Slaby3b85b342006-12-08 02:39:10 -08002192 retval = pci_enable_device(pdev);
2193 if (retval)
2194 goto err;
2195 brdp = stl_allocbrd();
2196 if (brdp == NULL) {
2197 retval = -ENOMEM;
2198 goto err;
2199 }
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002200 mutex_lock(&stl_brdslock);
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002201 brdnr = stl_getbrdnr();
2202 if (brdnr < 0) {
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002203 dev_err(&pdev->dev, "too many boards found, "
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204 "maximum supported %d\n", STL_MAXBRDS);
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002205 mutex_unlock(&stl_brdslock);
Jiri Slaby49277b12007-06-08 13:46:53 -07002206 retval = -ENODEV;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002207 goto err_fr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 }
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002209 brdp->brdnr = (unsigned int)brdnr;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002210 stl_brds[brdp->brdnr] = brdp;
2211 mutex_unlock(&stl_brdslock);
2212
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 brdp->brdtype = brdtype;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08002214 brdp->state |= STL_PROBED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
2216/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 * We have all resources from the board, so let's setup the actual
2218 * board structure now.
2219 */
2220 switch (brdtype) {
2221 case BRD_ECHPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002222 brdp->ioaddr2 = pci_resource_start(pdev, 0);
2223 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 break;
2225 case BRD_ECH64PCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002226 brdp->ioaddr2 = pci_resource_start(pdev, 2);
2227 brdp->ioaddr1 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 break;
2229 case BRD_EASYIOPCI:
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002230 brdp->ioaddr1 = pci_resource_start(pdev, 2);
2231 brdp->ioaddr2 = pci_resource_start(pdev, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 break;
2233 default:
Jiri Slabyfefaf9a2006-12-08 02:39:09 -08002234 dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 break;
2236 }
2237
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002238 brdp->irq = pdev->irq;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002239 retval = stl_brdinit(brdp);
2240 if (retval)
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002241 goto err_null;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002243 pci_set_drvdata(pdev, brdp);
2244
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002245 for (i = 0; i < brdp->nrports; i++)
2246 tty_register_device(stl_serial,
2247 brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
2248
Jiri Slaby3b85b342006-12-08 02:39:10 -08002249 return 0;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08002250err_null:
2251 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby3b85b342006-12-08 02:39:10 -08002252err_fr:
2253 kfree(brdp);
2254err:
2255 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256}
2257
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002258static void __devexit stl_pciremove(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259{
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002260 struct stlbrd *brdp = pci_get_drvdata(pdev);
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002261 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002263 free_irq(brdp->irq, brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002265 stl_cleanup_panels(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002267 release_region(brdp->ioaddr1, brdp->iosize1);
2268 if (brdp->iosize2 > 0)
2269 release_region(brdp->ioaddr2, brdp->iosize2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08002271 for (i = 0; i < brdp->nrports; i++)
2272 tty_unregister_device(stl_serial,
2273 brdp->brdnr * STL_MAXPORTS + i);
2274
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002275 stl_brds[brdp->brdnr] = NULL;
2276 kfree(brdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277}
2278
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08002279static struct pci_driver stl_pcidriver = {
2280 .name = "stallion",
2281 .id_table = stl_pcibrds,
2282 .probe = stl_pciprobe,
2283 .remove = __devexit_p(stl_pciremove)
2284};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
2286/*****************************************************************************/
2287
2288/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 * Return the board stats structure to user app.
2290 */
2291
2292static int stl_getbrdstats(combrd_t __user *bp)
2293{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002294 combrd_t stl_brdstats;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002295 struct stlbrd *brdp;
2296 struct stlpanel *panelp;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002297 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
2299 if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
2300 return -EFAULT;
2301 if (stl_brdstats.brd >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002302 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 brdp = stl_brds[stl_brdstats.brd];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002304 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002305 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
2307 memset(&stl_brdstats, 0, sizeof(combrd_t));
2308 stl_brdstats.brd = brdp->brdnr;
2309 stl_brdstats.type = brdp->brdtype;
2310 stl_brdstats.hwid = brdp->hwid;
2311 stl_brdstats.state = brdp->state;
2312 stl_brdstats.ioaddr = brdp->ioaddr1;
2313 stl_brdstats.ioaddr2 = brdp->ioaddr2;
2314 stl_brdstats.irq = brdp->irq;
2315 stl_brdstats.nrpanels = brdp->nrpanels;
2316 stl_brdstats.nrports = brdp->nrports;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002317 for (i = 0; i < brdp->nrpanels; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 panelp = brdp->panels[i];
2319 stl_brdstats.panels[i].panel = i;
2320 stl_brdstats.panels[i].hwid = panelp->hwid;
2321 stl_brdstats.panels[i].nrports = panelp->nrports;
2322 }
2323
2324 return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
2325}
2326
2327/*****************************************************************************/
2328
2329/*
2330 * Resolve the referenced port number into a port struct pointer.
2331 */
2332
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002333static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002335 struct stlbrd *brdp;
2336 struct stlpanel *panelp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
Jiri Slabyc62429d2006-12-08 02:39:14 -08002338 if (brdnr < 0 || brdnr >= STL_MAXBRDS)
2339 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 brdp = stl_brds[brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002341 if (brdp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002342 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002343 if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002344 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 panelp = brdp->panels[panelnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002346 if (panelp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002347 return NULL;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002348 if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002349 return NULL;
2350 return panelp->ports[portnr];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351}
2352
2353/*****************************************************************************/
2354
2355/*
2356 * Return the port stats structure to user app. A NULL port struct
2357 * pointer passed in means that we need to find out from the app
2358 * what port to get stats for (used through board control device).
2359 */
2360
Alan Coxd18a7502008-10-13 10:40:07 +01002361static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002363 comstats_t stl_comstats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 unsigned char *head, *tail;
2365 unsigned long flags;
2366
2367 if (!portp) {
2368 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2369 return -EFAULT;
2370 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2371 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002372 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002373 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 }
2375
2376 portp->stats.state = portp->istate;
Alan Coxf8ae4762008-07-16 21:56:37 +01002377 portp->stats.flags = portp->port.flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 portp->stats.hwid = portp->hwid;
2379
2380 portp->stats.ttystate = 0;
2381 portp->stats.cflags = 0;
2382 portp->stats.iflags = 0;
2383 portp->stats.oflags = 0;
2384 portp->stats.lflags = 0;
2385 portp->stats.rxbuffered = 0;
2386
Alan Coxb65b5b52006-06-27 02:54:05 -07002387 spin_lock_irqsave(&stallion_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01002388 if (tty != NULL && portp->port.tty == tty) {
2389 portp->stats.ttystate = tty->flags;
2390 /* No longer available as a statistic */
2391 portp->stats.rxbuffered = 1; /*tty->flip.count; */
2392 if (tty->termios != NULL) {
2393 portp->stats.cflags = tty->termios->c_cflag;
2394 portp->stats.iflags = tty->termios->c_iflag;
2395 portp->stats.oflags = tty->termios->c_oflag;
2396 portp->stats.lflags = tty->termios->c_lflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 }
Alan Coxd18a7502008-10-13 10:40:07 +01002398 }
Alan Coxb65b5b52006-06-27 02:54:05 -07002399 spin_unlock_irqrestore(&stallion_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
2401 head = portp->tx.head;
2402 tail = portp->tx.tail;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002403 portp->stats.txbuffered = (head >= tail) ? (head - tail) :
2404 (STL_TXBUFSIZE - (tail - head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
2406 portp->stats.signals = (unsigned long) stl_getsignals(portp);
2407
2408 return copy_to_user(cp, &portp->stats,
2409 sizeof(comstats_t)) ? -EFAULT : 0;
2410}
2411
2412/*****************************************************************************/
2413
2414/*
2415 * Clear the port stats structure. We also return it zeroed out...
2416 */
2417
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002418static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002420 comstats_t stl_comstats;
2421
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 if (!portp) {
2423 if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
2424 return -EFAULT;
2425 portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
2426 stl_comstats.port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08002427 if (portp == NULL)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002428 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 }
2430
2431 memset(&portp->stats, 0, sizeof(comstats_t));
2432 portp->stats.brd = portp->brdnr;
2433 portp->stats.panel = portp->panelnr;
2434 portp->stats.port = portp->portnr;
2435 return copy_to_user(cp, &portp->stats,
2436 sizeof(comstats_t)) ? -EFAULT : 0;
2437}
2438
2439/*****************************************************************************/
2440
2441/*
2442 * Return the entire driver ports structure to a user app.
2443 */
2444
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002445static int stl_getportstruct(struct stlport __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002447 struct stlport stl_dummyport;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002448 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002450 if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 return -EFAULT;
2452 portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
2453 stl_dummyport.portnr);
2454 if (!portp)
2455 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002456 return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457}
2458
2459/*****************************************************************************/
2460
2461/*
2462 * Return the entire driver board structure to a user app.
2463 */
2464
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002465static int stl_getbrdstruct(struct stlbrd __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466{
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002467 struct stlbrd stl_dummybrd;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002468 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002470 if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 return -EFAULT;
Jiri Slaby6b2c9452006-12-08 02:39:15 -08002472 if (stl_dummybrd.brdnr >= STL_MAXBRDS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 return -ENODEV;
2474 brdp = stl_brds[stl_dummybrd.brdnr];
2475 if (!brdp)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002476 return -ENODEV;
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002477 return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478}
2479
2480/*****************************************************************************/
2481
2482/*
2483 * The "staliomem" device is also required to do some special operations
2484 * on the board and/or ports. In this driver it is mostly used for stats
2485 * collection.
2486 */
2487
2488static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
2489{
2490 int brdnr, rc;
2491 void __user *argp = (void __user *)arg;
2492
Jiri Slabya0564e12006-12-08 02:38:37 -08002493 pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 brdnr = iminor(ip);
2496 if (brdnr >= STL_MAXBRDS)
Jiri Slabyc62429d2006-12-08 02:39:14 -08002497 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 rc = 0;
2499
2500 switch (cmd) {
2501 case COM_GETPORTSTATS:
Alan Coxd18a7502008-10-13 10:40:07 +01002502 rc = stl_getportstats(NULL, NULL, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 break;
2504 case COM_CLRPORTSTATS:
2505 rc = stl_clrportstats(NULL, argp);
2506 break;
2507 case COM_GETBRDSTATS:
2508 rc = stl_getbrdstats(argp);
2509 break;
2510 case COM_READPORT:
2511 rc = stl_getportstruct(argp);
2512 break;
2513 case COM_READBOARD:
2514 rc = stl_getbrdstruct(argp);
2515 break;
2516 default:
2517 rc = -ENOIOCTLCMD;
2518 break;
2519 }
2520
Jiri Slabyc62429d2006-12-08 02:39:14 -08002521 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522}
2523
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002524static const struct tty_operations stl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 .open = stl_open,
2526 .close = stl_close,
2527 .write = stl_write,
2528 .put_char = stl_putchar,
2529 .flush_chars = stl_flushchars,
2530 .write_room = stl_writeroom,
2531 .chars_in_buffer = stl_charsinbuffer,
2532 .ioctl = stl_ioctl,
2533 .set_termios = stl_settermios,
2534 .throttle = stl_throttle,
2535 .unthrottle = stl_unthrottle,
2536 .stop = stl_stop,
2537 .start = stl_start,
2538 .hangup = stl_hangup,
2539 .flush_buffer = stl_flushbuffer,
2540 .break_ctl = stl_breakctl,
2541 .wait_until_sent = stl_waituntilsent,
2542 .send_xchar = stl_sendxchar,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 .tiocmget = stl_tiocmget,
2544 .tiocmset = stl_tiocmset,
Alexey Dobriyan8561c442009-03-31 15:19:18 -07002545 .proc_fops = &stl_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546};
2547
Alan Cox31f35932009-01-02 13:45:05 +00002548static const struct tty_port_operations stl_port_ops = {
2549 .carrier_raised = stl_carrier_raised,
Alan Coxfcc8ac12009-06-11 12:24:17 +01002550 .dtr_rts = stl_dtr_rts,
Alan Cox31f35932009-01-02 13:45:05 +00002551};
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553/*****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554/* CD1400 HARDWARE FUNCTIONS */
2555/*****************************************************************************/
2556
2557/*
2558 * These functions get/set/update the registers of the cd1400 UARTs.
2559 * Access to the cd1400 registers is via an address/data io port pair.
2560 * (Maybe should make this inline...)
2561 */
2562
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002563static int stl_cd1400getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564{
2565 outb((regnr + portp->uartaddr), portp->ioaddr);
Jesper Juhl014c2542006-01-15 02:37:08 +01002566 return inb(portp->ioaddr + EREG_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567}
2568
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002569static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002571 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 outb(value, portp->ioaddr + EREG_DATA);
2573}
2574
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002575static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576{
Jiri Slabyc62429d2006-12-08 02:39:14 -08002577 outb(regnr + portp->uartaddr, portp->ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 if (inb(portp->ioaddr + EREG_DATA) != value) {
2579 outb(value, portp->ioaddr + EREG_DATA);
Jesper Juhl014c2542006-01-15 02:37:08 +01002580 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 }
Jesper Juhl014c2542006-01-15 02:37:08 +01002582 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583}
2584
2585/*****************************************************************************/
2586
2587/*
2588 * Inbitialize the UARTs in a panel. We don't care what sort of board
2589 * these ports are on - since the port io registers are almost
2590 * identical when dealing with ports.
2591 */
2592
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002593static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594{
2595 unsigned int gfrcr;
2596 int chipmask, i, j;
2597 int nrchips, uartaddr, ioaddr;
Alan Coxb65b5b52006-06-27 02:54:05 -07002598 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Jiri Slabya0564e12006-12-08 02:38:37 -08002600 pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
Alan Coxb65b5b52006-06-27 02:54:05 -07002602 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 BRDENABLE(panelp->brdnr, panelp->pagenr);
2604
2605/*
2606 * Check that each chip is present and started up OK.
2607 */
2608 chipmask = 0;
2609 nrchips = panelp->nrports / CD1400_PORTS;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002610 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 if (brdp->brdtype == BRD_ECHPCI) {
2612 outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
2613 ioaddr = panelp->iobase;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002614 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 uartaddr = (i & 0x01) ? 0x080 : 0;
2617 outb((GFRCR + uartaddr), ioaddr);
2618 outb(0, (ioaddr + EREG_DATA));
2619 outb((CCR + uartaddr), ioaddr);
2620 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2621 outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
2622 outb((GFRCR + uartaddr), ioaddr);
Jiri Slabyc62429d2006-12-08 02:39:14 -08002623 for (j = 0; j < CCR_MAXWAIT; j++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
2625 break;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002626
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
2628 printk("STALLION: cd1400 not responding, "
2629 "brd=%d panel=%d chip=%d\n",
2630 panelp->brdnr, panelp->panelnr, i);
2631 continue;
2632 }
2633 chipmask |= (0x1 << i);
2634 outb((PPR + uartaddr), ioaddr);
2635 outb(PPR_SCALAR, (ioaddr + EREG_DATA));
2636 }
2637
2638 BRDDISABLE(panelp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002639 spin_unlock_irqrestore(&brd_lock, flags);
Jesper Juhl014c2542006-01-15 02:37:08 +01002640 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641}
2642
2643/*****************************************************************************/
2644
2645/*
2646 * Initialize hardware specific port registers.
2647 */
2648
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002649static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650{
Alan Coxb65b5b52006-06-27 02:54:05 -07002651 unsigned long flags;
Jiri Slabya0564e12006-12-08 02:38:37 -08002652 pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
2653 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654
Jiri Slaby615e4a72006-12-08 02:38:38 -08002655 if ((brdp == NULL) || (panelp == NULL) ||
2656 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 return;
2658
Alan Coxb65b5b52006-06-27 02:54:05 -07002659 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
2661 (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
2662 portp->uartaddr = (portp->portnr & 0x04) << 5;
2663 portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
2664
2665 BRDENABLE(portp->brdnr, portp->pagenr);
2666 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2667 stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
2668 portp->hwid = stl_cd1400getreg(portp, GFRCR);
2669 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002670 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671}
2672
2673/*****************************************************************************/
2674
2675/*
2676 * Wait for the command register to be ready. We will poll this,
2677 * since it won't usually take too long to be ready.
2678 */
2679
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002680static void stl_cd1400ccrwait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681{
2682 int i;
2683
Jiri Slabyc62429d2006-12-08 02:39:14 -08002684 for (i = 0; i < CCR_MAXWAIT; i++)
2685 if (stl_cd1400getreg(portp, CCR) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
2688 printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
2689 portp->portnr, portp->panelnr, portp->brdnr);
2690}
2691
2692/*****************************************************************************/
2693
2694/*
2695 * Set up the cd1400 registers for a port based on the termios port
2696 * settings.
2697 */
2698
Alan Cox606d0992006-12-08 02:38:45 -08002699static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002701 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 unsigned long flags;
2703 unsigned int clkdiv, baudrate;
2704 unsigned char cor1, cor2, cor3;
2705 unsigned char cor4, cor5, ccr;
2706 unsigned char srer, sreron, sreroff;
2707 unsigned char mcor1, mcor2, rtpr;
2708 unsigned char clk, div;
2709
2710 cor1 = 0;
2711 cor2 = 0;
2712 cor3 = 0;
2713 cor4 = 0;
2714 cor5 = 0;
2715 ccr = 0;
2716 rtpr = 0;
2717 clk = 0;
2718 div = 0;
2719 mcor1 = 0;
2720 mcor2 = 0;
2721 sreron = 0;
2722 sreroff = 0;
2723
2724 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08002725 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 return;
2727
2728/*
2729 * Set up the RX char ignore mask with those RX error types we
2730 * can ignore. We can get the cd1400 to help us out a little here,
2731 * it will ignore parity errors and breaks for us.
2732 */
2733 portp->rxignoremsk = 0;
2734 if (tiosp->c_iflag & IGNPAR) {
2735 portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
2736 cor1 |= COR1_PARIGNORE;
2737 }
2738 if (tiosp->c_iflag & IGNBRK) {
2739 portp->rxignoremsk |= ST_BREAK;
2740 cor4 |= COR4_IGNBRK;
2741 }
2742
2743 portp->rxmarkmsk = ST_OVERRUN;
2744 if (tiosp->c_iflag & (INPCK | PARMRK))
2745 portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
2746 if (tiosp->c_iflag & BRKINT)
2747 portp->rxmarkmsk |= ST_BREAK;
2748
2749/*
2750 * Go through the char size, parity and stop bits and set all the
2751 * option register appropriately.
2752 */
2753 switch (tiosp->c_cflag & CSIZE) {
2754 case CS5:
2755 cor1 |= COR1_CHL5;
2756 break;
2757 case CS6:
2758 cor1 |= COR1_CHL6;
2759 break;
2760 case CS7:
2761 cor1 |= COR1_CHL7;
2762 break;
2763 default:
2764 cor1 |= COR1_CHL8;
2765 break;
2766 }
2767
2768 if (tiosp->c_cflag & CSTOPB)
2769 cor1 |= COR1_STOP2;
2770 else
2771 cor1 |= COR1_STOP1;
2772
2773 if (tiosp->c_cflag & PARENB) {
2774 if (tiosp->c_cflag & PARODD)
2775 cor1 |= (COR1_PARENB | COR1_PARODD);
2776 else
2777 cor1 |= (COR1_PARENB | COR1_PAREVEN);
2778 } else {
2779 cor1 |= COR1_PARNONE;
2780 }
2781
2782/*
2783 * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
2784 * space for hardware flow control and the like. This should be set to
2785 * VMIN. Also here we will set the RX data timeout to 10ms - this should
2786 * really be based on VTIME.
2787 */
2788 cor3 |= FIFO_RXTHRESHOLD;
2789 rtpr = 2;
2790
2791/*
2792 * Calculate the baud rate timers. For now we will just assume that
2793 * the input and output baud are the same. Could have used a baud
2794 * table here, but this way we can generate virtually any baud rate
2795 * we like!
2796 */
2797 baudrate = tiosp->c_cflag & CBAUD;
2798 if (baudrate & CBAUDEX) {
2799 baudrate &= ~CBAUDEX;
2800 if ((baudrate < 1) || (baudrate > 4))
2801 tiosp->c_cflag &= ~CBAUDEX;
2802 else
2803 baudrate += 15;
2804 }
2805 baudrate = stl_baudrates[baudrate];
2806 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01002807 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01002809 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01002811 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01002813 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01002815 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 baudrate = (portp->baud_base / portp->custom_divisor);
2817 }
2818 if (baudrate > STL_CD1400MAXBAUD)
2819 baudrate = STL_CD1400MAXBAUD;
2820
2821 if (baudrate > 0) {
Jiri Slabyc62429d2006-12-08 02:39:14 -08002822 for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
2823 clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 if (clkdiv < 0x100)
2825 break;
2826 }
2827 div = (unsigned char) clkdiv;
2828 }
2829
2830/*
2831 * Check what form of modem signaling is required and set it up.
2832 */
2833 if ((tiosp->c_cflag & CLOCAL) == 0) {
2834 mcor1 |= MCOR1_DCD;
2835 mcor2 |= MCOR2_DCD;
2836 sreron |= SRER_MODEM;
Alan Coxf8ae4762008-07-16 21:56:37 +01002837 portp->port.flags |= ASYNC_CHECK_CD;
Jiri Slabyc62429d2006-12-08 02:39:14 -08002838 } else
Alan Coxf8ae4762008-07-16 21:56:37 +01002839 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840
2841/*
2842 * Setup cd1400 enhanced modes if we can. In particular we want to
2843 * handle as much of the flow control as possible automatically. As
2844 * well as saving a few CPU cycles it will also greatly improve flow
2845 * control reliability.
2846 */
2847 if (tiosp->c_iflag & IXON) {
2848 cor2 |= COR2_TXIBE;
2849 cor3 |= COR3_SCD12;
2850 if (tiosp->c_iflag & IXANY)
2851 cor2 |= COR2_IXM;
2852 }
2853
2854 if (tiosp->c_cflag & CRTSCTS) {
2855 cor2 |= COR2_CTSAE;
2856 mcor1 |= FIFO_RTSTHRESHOLD;
2857 }
2858
2859/*
2860 * All cd1400 register values calculated so go through and set
2861 * them all up.
2862 */
2863
Jiri Slabya0564e12006-12-08 02:38:37 -08002864 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08002866 pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867 cor1, cor2, cor3, cor4, cor5);
Jiri Slabya0564e12006-12-08 02:38:37 -08002868 pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 mcor1, mcor2, rtpr, sreron, sreroff);
Jiri Slabya0564e12006-12-08 02:38:37 -08002870 pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
2871 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
2873 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Alan Coxb65b5b52006-06-27 02:54:05 -07002875 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 BRDENABLE(portp->brdnr, portp->pagenr);
2877 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
2878 srer = stl_cd1400getreg(portp, SRER);
2879 stl_cd1400setreg(portp, SRER, 0);
2880 if (stl_cd1400updatereg(portp, COR1, cor1))
2881 ccr = 1;
2882 if (stl_cd1400updatereg(portp, COR2, cor2))
2883 ccr = 1;
2884 if (stl_cd1400updatereg(portp, COR3, cor3))
2885 ccr = 1;
2886 if (ccr) {
2887 stl_cd1400ccrwait(portp);
2888 stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
2889 }
2890 stl_cd1400setreg(portp, COR4, cor4);
2891 stl_cd1400setreg(portp, COR5, cor5);
2892 stl_cd1400setreg(portp, MCOR1, mcor1);
2893 stl_cd1400setreg(portp, MCOR2, mcor2);
2894 if (baudrate > 0) {
2895 stl_cd1400setreg(portp, TCOR, clk);
2896 stl_cd1400setreg(portp, TBPR, div);
2897 stl_cd1400setreg(portp, RCOR, clk);
2898 stl_cd1400setreg(portp, RBPR, div);
2899 }
2900 stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
2901 stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
2902 stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
2903 stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
2904 stl_cd1400setreg(portp, RTPR, rtpr);
2905 mcor1 = stl_cd1400getreg(portp, MSVR1);
2906 if (mcor1 & MSVR1_DCD)
2907 portp->sigs |= TIOCM_CD;
2908 else
2909 portp->sigs &= ~TIOCM_CD;
2910 stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
2911 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002912 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913}
2914
2915/*****************************************************************************/
2916
2917/*
2918 * Set the state of the DTR and RTS signals.
2919 */
2920
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002921static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922{
2923 unsigned char msvr1, msvr2;
2924 unsigned long flags;
2925
Jiri Slabya0564e12006-12-08 02:38:37 -08002926 pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
2927 portp, dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928
2929 msvr1 = 0;
2930 msvr2 = 0;
2931 if (dtr > 0)
2932 msvr1 = MSVR1_DTR;
2933 if (rts > 0)
2934 msvr2 = MSVR2_RTS;
2935
Alan Coxb65b5b52006-06-27 02:54:05 -07002936 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 BRDENABLE(portp->brdnr, portp->pagenr);
2938 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2939 if (rts >= 0)
2940 stl_cd1400setreg(portp, MSVR2, msvr2);
2941 if (dtr >= 0)
2942 stl_cd1400setreg(portp, MSVR1, msvr1);
2943 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002944 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945}
2946
2947/*****************************************************************************/
2948
2949/*
2950 * Return the state of the signals.
2951 */
2952
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002953static int stl_cd1400getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
2955 unsigned char msvr1, msvr2;
2956 unsigned long flags;
2957 int sigs;
2958
Jiri Slabya0564e12006-12-08 02:38:37 -08002959 pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
Alan Coxb65b5b52006-06-27 02:54:05 -07002961 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 BRDENABLE(portp->brdnr, portp->pagenr);
2963 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
2964 msvr1 = stl_cd1400getreg(portp, MSVR1);
2965 msvr2 = stl_cd1400getreg(portp, MSVR2);
2966 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07002967 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
2969 sigs = 0;
2970 sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
2971 sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
2972 sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
2973 sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
2974#if 0
2975 sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
2976 sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
2977#else
2978 sigs |= TIOCM_DSR;
2979#endif
Jesper Juhl014c2542006-01-15 02:37:08 +01002980 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981}
2982
2983/*****************************************************************************/
2984
2985/*
2986 * Enable/Disable the Transmitter and/or Receiver.
2987 */
2988
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08002989static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990{
2991 unsigned char ccr;
2992 unsigned long flags;
2993
Jiri Slabya0564e12006-12-08 02:38:37 -08002994 pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
2995
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 ccr = 0;
2997
2998 if (tx == 0)
2999 ccr |= CCR_TXDISABLE;
3000 else if (tx > 0)
3001 ccr |= CCR_TXENABLE;
3002 if (rx == 0)
3003 ccr |= CCR_RXDISABLE;
3004 else if (rx > 0)
3005 ccr |= CCR_RXENABLE;
3006
Alan Coxb65b5b52006-06-27 02:54:05 -07003007 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 BRDENABLE(portp->brdnr, portp->pagenr);
3009 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3010 stl_cd1400ccrwait(portp);
3011 stl_cd1400setreg(portp, CCR, ccr);
3012 stl_cd1400ccrwait(portp);
3013 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003014 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015}
3016
3017/*****************************************************************************/
3018
3019/*
3020 * Start/stop the Transmitter and/or Receiver.
3021 */
3022
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003023static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024{
3025 unsigned char sreron, sreroff;
3026 unsigned long flags;
3027
Jiri Slabya0564e12006-12-08 02:38:37 -08003028 pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029
3030 sreron = 0;
3031 sreroff = 0;
3032 if (tx == 0)
3033 sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
3034 else if (tx == 1)
3035 sreron |= SRER_TXDATA;
3036 else if (tx >= 2)
3037 sreron |= SRER_TXEMPTY;
3038 if (rx == 0)
3039 sreroff |= SRER_RXDATA;
3040 else if (rx > 0)
3041 sreron |= SRER_RXDATA;
3042
Alan Coxb65b5b52006-06-27 02:54:05 -07003043 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 BRDENABLE(portp->brdnr, portp->pagenr);
3045 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3046 stl_cd1400setreg(portp, SRER,
3047 ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
3048 BRDDISABLE(portp->brdnr);
3049 if (tx > 0)
3050 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003051 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052}
3053
3054/*****************************************************************************/
3055
3056/*
3057 * Disable all interrupts from this port.
3058 */
3059
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003060static void stl_cd1400disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061{
3062 unsigned long flags;
3063
Jiri Slabya0564e12006-12-08 02:38:37 -08003064 pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
3065
Alan Coxb65b5b52006-06-27 02:54:05 -07003066 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 BRDENABLE(portp->brdnr, portp->pagenr);
3068 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3069 stl_cd1400setreg(portp, SRER, 0);
3070 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003071 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072}
3073
3074/*****************************************************************************/
3075
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003076static void stl_cd1400sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077{
3078 unsigned long flags;
3079
Jiri Slabya0564e12006-12-08 02:38:37 -08003080 pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Alan Coxb65b5b52006-06-27 02:54:05 -07003082 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 BRDENABLE(portp->brdnr, portp->pagenr);
3084 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3085 stl_cd1400setreg(portp, SRER,
3086 ((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
3087 SRER_TXEMPTY));
3088 BRDDISABLE(portp->brdnr);
3089 portp->brklen = len;
3090 if (len == 1)
3091 portp->stats.txbreaks++;
Alan Coxb65b5b52006-06-27 02:54:05 -07003092 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093}
3094
3095/*****************************************************************************/
3096
3097/*
3098 * Take flow control actions...
3099 */
3100
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003101static void stl_cd1400flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102{
3103 struct tty_struct *tty;
3104 unsigned long flags;
3105
Jiri Slabya0564e12006-12-08 02:38:37 -08003106 pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
Jiri Slaby615e4a72006-12-08 02:38:38 -08003108 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003110 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003111 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 return;
3113
Alan Coxb65b5b52006-06-27 02:54:05 -07003114 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 BRDENABLE(portp->brdnr, portp->pagenr);
3116 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3117
3118 if (state) {
3119 if (tty->termios->c_iflag & IXOFF) {
3120 stl_cd1400ccrwait(portp);
3121 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3122 portp->stats.rxxon++;
3123 stl_cd1400ccrwait(portp);
3124 }
3125/*
3126 * Question: should we return RTS to what it was before? It may
3127 * have been set by an ioctl... Suppose not, since if you have
3128 * hardware flow control set then it is pretty silly to go and
3129 * set the RTS line by hand.
3130 */
3131 if (tty->termios->c_cflag & CRTSCTS) {
3132 stl_cd1400setreg(portp, MCOR1,
3133 (stl_cd1400getreg(portp, MCOR1) |
3134 FIFO_RTSTHRESHOLD));
3135 stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
3136 portp->stats.rxrtson++;
3137 }
3138 } else {
3139 if (tty->termios->c_iflag & IXOFF) {
3140 stl_cd1400ccrwait(portp);
3141 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3142 portp->stats.rxxoff++;
3143 stl_cd1400ccrwait(portp);
3144 }
3145 if (tty->termios->c_cflag & CRTSCTS) {
3146 stl_cd1400setreg(portp, MCOR1,
3147 (stl_cd1400getreg(portp, MCOR1) & 0xf0));
3148 stl_cd1400setreg(portp, MSVR2, 0);
3149 portp->stats.rxrtsoff++;
3150 }
3151 }
3152
3153 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003154 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003155 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156}
3157
3158/*****************************************************************************/
3159
3160/*
3161 * Send a flow control character...
3162 */
3163
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003164static void stl_cd1400sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165{
3166 struct tty_struct *tty;
3167 unsigned long flags;
3168
Jiri Slabya0564e12006-12-08 02:38:37 -08003169 pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Jiri Slaby615e4a72006-12-08 02:38:38 -08003171 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 return;
Alan Coxd18a7502008-10-13 10:40:07 +01003173 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08003174 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 return;
3176
Alan Coxb65b5b52006-06-27 02:54:05 -07003177 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 BRDENABLE(portp->brdnr, portp->pagenr);
3179 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3180 if (state) {
3181 stl_cd1400ccrwait(portp);
3182 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
3183 portp->stats.rxxon++;
3184 stl_cd1400ccrwait(portp);
3185 } else {
3186 stl_cd1400ccrwait(portp);
3187 stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
3188 portp->stats.rxxoff++;
3189 stl_cd1400ccrwait(portp);
3190 }
3191 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003192 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01003193 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194}
3195
3196/*****************************************************************************/
3197
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003198static void stl_cd1400flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199{
3200 unsigned long flags;
3201
Jiri Slabya0564e12006-12-08 02:38:37 -08003202 pr_debug("stl_cd1400flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203
Jiri Slaby615e4a72006-12-08 02:38:38 -08003204 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 return;
3206
Alan Coxb65b5b52006-06-27 02:54:05 -07003207 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 BRDENABLE(portp->brdnr, portp->pagenr);
3209 stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
3210 stl_cd1400ccrwait(portp);
3211 stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
3212 stl_cd1400ccrwait(portp);
3213 portp->tx.tail = portp->tx.head;
3214 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003215 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216}
3217
3218/*****************************************************************************/
3219
3220/*
3221 * Return the current state of data flow on this port. This is only
3222 * really interresting when determining if data has fully completed
3223 * transmission or not... This is easy for the cd1400, it accurately
3224 * maintains the busy port flag.
3225 */
3226
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003227static int stl_cd1400datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228{
Jiri Slabya0564e12006-12-08 02:38:37 -08003229 pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
Jiri Slaby615e4a72006-12-08 02:38:38 -08003231 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01003232 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233
Jesper Juhl014c2542006-01-15 02:37:08 +01003234 return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235}
3236
3237/*****************************************************************************/
3238
3239/*
3240 * Interrupt service routine for cd1400 EasyIO boards.
3241 */
3242
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003243static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244{
3245 unsigned char svrtype;
3246
Jiri Slabya0564e12006-12-08 02:38:37 -08003247 pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Alan Coxb65b5b52006-06-27 02:54:05 -07003249 spin_lock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250 outb(SVRR, iobase);
3251 svrtype = inb(iobase + EREG_DATA);
3252 if (panelp->nrports > 4) {
3253 outb((SVRR + 0x80), iobase);
3254 svrtype |= inb(iobase + EREG_DATA);
3255 }
3256
3257 if (svrtype & SVRR_RX)
3258 stl_cd1400rxisr(panelp, iobase);
3259 else if (svrtype & SVRR_TX)
3260 stl_cd1400txisr(panelp, iobase);
3261 else if (svrtype & SVRR_MDM)
3262 stl_cd1400mdmisr(panelp, iobase);
Alan Coxb65b5b52006-06-27 02:54:05 -07003263
3264 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265}
3266
3267/*****************************************************************************/
3268
3269/*
3270 * Interrupt service routine for cd1400 panels.
3271 */
3272
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003273static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274{
3275 unsigned char svrtype;
3276
Jiri Slabya0564e12006-12-08 02:38:37 -08003277 pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278
3279 outb(SVRR, iobase);
3280 svrtype = inb(iobase + EREG_DATA);
3281 outb((SVRR + 0x80), iobase);
3282 svrtype |= inb(iobase + EREG_DATA);
3283 if (svrtype & SVRR_RX)
3284 stl_cd1400rxisr(panelp, iobase);
3285 else if (svrtype & SVRR_TX)
3286 stl_cd1400txisr(panelp, iobase);
3287 else if (svrtype & SVRR_MDM)
3288 stl_cd1400mdmisr(panelp, iobase);
3289}
3290
3291
3292/*****************************************************************************/
3293
3294/*
3295 * Unfortunately we need to handle breaks in the TX data stream, since
3296 * this is the only way to generate them on the cd1400.
3297 */
3298
Jiri Slaby60be4812006-12-08 02:38:40 -08003299static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300{
3301 if (portp->brklen == 1) {
3302 outb((COR2 + portp->uartaddr), ioaddr);
3303 outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
3304 (ioaddr + EREG_DATA));
3305 outb((TDR + portp->uartaddr), ioaddr);
3306 outb(ETC_CMD, (ioaddr + EREG_DATA));
3307 outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
3308 outb((SRER + portp->uartaddr), ioaddr);
3309 outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
3310 (ioaddr + EREG_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003311 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 } else if (portp->brklen > 1) {
3313 outb((TDR + portp->uartaddr), ioaddr);
3314 outb(ETC_CMD, (ioaddr + EREG_DATA));
3315 outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
3316 portp->brklen = -1;
Jesper Juhl014c2542006-01-15 02:37:08 +01003317 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318 } else {
3319 outb((COR2 + portp->uartaddr), ioaddr);
3320 outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
3321 (ioaddr + EREG_DATA));
3322 portp->brklen = 0;
3323 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003324 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325}
3326
3327/*****************************************************************************/
3328
3329/*
3330 * Transmit interrupt handler. This has gotta be fast! Handling TX
3331 * chars is pretty simple, stuff as many as possible from the TX buffer
3332 * into the cd1400 FIFO. Must also handle TX breaks here, since they
3333 * are embedded as commands in the data stream. Oh no, had to use a goto!
3334 * This could be optimized more, will do when I get time...
3335 * In practice it is possible that interrupts are enabled but that the
3336 * port has been hung up. Need to handle not having any TX buffer here,
3337 * this is done by using the side effect that head and tail will also
3338 * be NULL if the buffer has been freed.
3339 */
3340
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003341static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003343 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 int len, stlen;
3345 char *head, *tail;
3346 unsigned char ioack, srer;
Alan Coxd18a7502008-10-13 10:40:07 +01003347 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
Jiri Slabya0564e12006-12-08 02:38:37 -08003349 pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350
3351 ioack = inb(ioaddr + EREG_TXACK);
3352 if (((ioack & panelp->ackmask) != 0) ||
3353 ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
3354 printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
3355 return;
3356 }
3357 portp = panelp->ports[(ioack >> 3)];
3358
3359/*
3360 * Unfortunately we need to handle breaks in the data stream, since
3361 * this is the only way to generate them on the cd1400. Do it now if
3362 * a break is to be sent.
3363 */
3364 if (portp->brklen != 0)
3365 if (stl_cd1400breakisr(portp, ioaddr))
3366 goto stl_txalldone;
3367
3368 head = portp->tx.head;
3369 tail = portp->tx.tail;
3370 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
3371 if ((len == 0) || ((len < STL_TXBUFLOW) &&
3372 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
3373 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01003374 tty = tty_port_tty_get(&portp->port);
3375 if (tty) {
3376 tty_wakeup(tty);
3377 tty_kref_put(tty);
3378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 }
3380
3381 if (len == 0) {
3382 outb((SRER + portp->uartaddr), ioaddr);
3383 srer = inb(ioaddr + EREG_DATA);
3384 if (srer & SRER_TXDATA) {
3385 srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
3386 } else {
3387 srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
3388 clear_bit(ASYI_TXBUSY, &portp->istate);
3389 }
3390 outb(srer, (ioaddr + EREG_DATA));
3391 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003392 len = min(len, CD1400_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003394 stlen = min_t(unsigned int, len,
3395 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 outb((TDR + portp->uartaddr), ioaddr);
3397 outsb((ioaddr + EREG_DATA), tail, stlen);
3398 len -= stlen;
3399 tail += stlen;
3400 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
3401 tail = portp->tx.buf;
3402 if (len > 0) {
3403 outsb((ioaddr + EREG_DATA), tail, len);
3404 tail += len;
3405 }
3406 portp->tx.tail = tail;
3407 }
3408
3409stl_txalldone:
3410 outb((EOSRR + portp->uartaddr), ioaddr);
3411 outb(0, (ioaddr + EREG_DATA));
3412}
3413
3414/*****************************************************************************/
3415
3416/*
3417 * Receive character interrupt handler. Determine if we have good chars
3418 * or bad chars and then process appropriately. Good chars are easy
3419 * just shove the lot into the RX buffer and set all status byte to 0.
3420 * If a bad RX char then process as required. This routine needs to be
3421 * fast! In practice it is possible that we get an interrupt on a port
3422 * that is closed. This can happen on hangups - since they completely
3423 * shutdown a port not in user context. Need to handle this case.
3424 */
3425
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003426static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003428 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 struct tty_struct *tty;
3430 unsigned int ioack, len, buflen;
3431 unsigned char status;
3432 char ch;
3433
Jiri Slabya0564e12006-12-08 02:38:37 -08003434 pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
3436 ioack = inb(ioaddr + EREG_RXACK);
3437 if ((ioack & panelp->ackmask) != 0) {
3438 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
3439 return;
3440 }
3441 portp = panelp->ports[(ioack >> 3)];
Alan Coxd18a7502008-10-13 10:40:07 +01003442 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443
3444 if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
3445 outb((RDCR + portp->uartaddr), ioaddr);
3446 len = inb(ioaddr + EREG_DATA);
Alan Cox33f0f882006-01-09 20:54:13 -08003447 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08003448 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 outb((RDSR + portp->uartaddr), ioaddr);
3450 insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
3451 portp->stats.rxlost += len;
3452 portp->stats.rxtotal += len;
3453 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08003454 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003455 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08003456 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 outb((RDSR + portp->uartaddr), ioaddr);
Alan Cox33f0f882006-01-09 20:54:13 -08003458 tty_prepare_flip_string(tty, &ptr, len);
3459 insb((ioaddr + EREG_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 tty_schedule_flip(tty);
3461 portp->stats.rxtotal += len;
3462 }
3463 }
3464 } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
3465 outb((RDSR + portp->uartaddr), ioaddr);
3466 status = inb(ioaddr + EREG_DATA);
3467 ch = inb(ioaddr + EREG_DATA);
3468 if (status & ST_PARITY)
3469 portp->stats.rxparity++;
3470 if (status & ST_FRAMING)
3471 portp->stats.rxframing++;
3472 if (status & ST_OVERRUN)
3473 portp->stats.rxoverrun++;
3474 if (status & ST_BREAK)
3475 portp->stats.rxbreaks++;
3476 if (status & ST_SCHARMASK) {
3477 if ((status & ST_SCHARMASK) == ST_SCHAR1)
3478 portp->stats.txxon++;
3479 if ((status & ST_SCHARMASK) == ST_SCHAR2)
3480 portp->stats.txxoff++;
3481 goto stl_rxalldone;
3482 }
Alan Cox33f0f882006-01-09 20:54:13 -08003483 if (tty != NULL && (portp->rxignoremsk & status) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 if (portp->rxmarkmsk & status) {
3485 if (status & ST_BREAK) {
3486 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01003487 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 do_SAK(tty);
3489 BRDENABLE(portp->brdnr, portp->pagenr);
3490 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08003491 } else if (status & ST_PARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003493 else if (status & ST_FRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003495 else if(status & ST_OVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003497 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003499 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 status = 0;
Alan Cox33f0f882006-01-09 20:54:13 -08003501 tty_insert_flip_char(tty, ch, status);
3502 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 }
3504 } else {
3505 printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
Alan Coxd18a7502008-10-13 10:40:07 +01003506 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 return;
3508 }
3509
3510stl_rxalldone:
Alan Coxd18a7502008-10-13 10:40:07 +01003511 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 outb((EOSRR + portp->uartaddr), ioaddr);
3513 outb(0, (ioaddr + EREG_DATA));
3514}
3515
3516/*****************************************************************************/
3517
3518/*
3519 * Modem interrupt handler. The is called when the modem signal line
3520 * (DCD) has changed state. Leave most of the work to the off-level
3521 * processing routine.
3522 */
3523
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003524static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003526 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527 unsigned int ioack;
3528 unsigned char misr;
3529
Jiri Slabya0564e12006-12-08 02:38:37 -08003530 pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531
3532 ioack = inb(ioaddr + EREG_MDACK);
3533 if (((ioack & panelp->ackmask) != 0) ||
3534 ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
3535 printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
3536 return;
3537 }
3538 portp = panelp->ports[(ioack >> 3)];
3539
3540 outb((MISR + portp->uartaddr), ioaddr);
3541 misr = inb(ioaddr + EREG_DATA);
3542 if (misr & MISR_DCD) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08003543 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 portp->stats.modem++;
3545 }
3546
3547 outb((EOSRR + portp->uartaddr), ioaddr);
3548 outb(0, (ioaddr + EREG_DATA));
3549}
3550
3551/*****************************************************************************/
3552/* SC26198 HARDWARE FUNCTIONS */
3553/*****************************************************************************/
3554
3555/*
3556 * These functions get/set/update the registers of the sc26198 UARTs.
3557 * Access to the sc26198 registers is via an address/data io port pair.
3558 * (Maybe should make this inline...)
3559 */
3560
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003561static int stl_sc26198getreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562{
3563 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003564 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565}
3566
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003567static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568{
3569 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3570 outb(value, (portp->ioaddr + XP_DATA));
3571}
3572
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003573static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574{
3575 outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
3576 if (inb(portp->ioaddr + XP_DATA) != value) {
3577 outb(value, (portp->ioaddr + XP_DATA));
Jesper Juhl014c2542006-01-15 02:37:08 +01003578 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 }
Jesper Juhl014c2542006-01-15 02:37:08 +01003580 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581}
3582
3583/*****************************************************************************/
3584
3585/*
3586 * Functions to get and set the sc26198 global registers.
3587 */
3588
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003589static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590{
3591 outb(regnr, (portp->ioaddr + XP_ADDR));
Jesper Juhl014c2542006-01-15 02:37:08 +01003592 return inb(portp->ioaddr + XP_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593}
3594
3595#if 0
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003596static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597{
3598 outb(regnr, (portp->ioaddr + XP_ADDR));
3599 outb(value, (portp->ioaddr + XP_DATA));
3600}
3601#endif
3602
3603/*****************************************************************************/
3604
3605/*
3606 * Inbitialize the UARTs in a panel. We don't care what sort of board
3607 * these ports are on - since the port io registers are almost
3608 * identical when dealing with ports.
3609 */
3610
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003611static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612{
3613 int chipmask, i;
3614 int nrchips, ioaddr;
3615
Jiri Slabya0564e12006-12-08 02:38:37 -08003616 pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
3618 BRDENABLE(panelp->brdnr, panelp->pagenr);
3619
3620/*
3621 * Check that each chip is present and started up OK.
3622 */
3623 chipmask = 0;
3624 nrchips = (panelp->nrports + 4) / SC26198_PORTS;
3625 if (brdp->brdtype == BRD_ECHPCI)
3626 outb(panelp->pagenr, brdp->ioctrl);
3627
Jiri Slabyc62429d2006-12-08 02:39:14 -08003628 for (i = 0; i < nrchips; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629 ioaddr = panelp->iobase + (i * 4);
3630 outb(SCCR, (ioaddr + XP_ADDR));
3631 outb(CR_RESETALL, (ioaddr + XP_DATA));
3632 outb(TSTR, (ioaddr + XP_ADDR));
3633 if (inb(ioaddr + XP_DATA) != 0) {
3634 printk("STALLION: sc26198 not responding, "
3635 "brd=%d panel=%d chip=%d\n",
3636 panelp->brdnr, panelp->panelnr, i);
3637 continue;
3638 }
3639 chipmask |= (0x1 << i);
3640 outb(GCCR, (ioaddr + XP_ADDR));
3641 outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
3642 outb(WDTRCR, (ioaddr + XP_ADDR));
3643 outb(0xff, (ioaddr + XP_DATA));
3644 }
3645
3646 BRDDISABLE(panelp->brdnr);
Jesper Juhl014c2542006-01-15 02:37:08 +01003647 return chipmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648}
3649
3650/*****************************************************************************/
3651
3652/*
3653 * Initialize hardware specific port registers.
3654 */
3655
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003656static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657{
Jiri Slabya0564e12006-12-08 02:38:37 -08003658 pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
3659 panelp, portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
Jiri Slaby615e4a72006-12-08 02:38:38 -08003661 if ((brdp == NULL) || (panelp == NULL) ||
3662 (portp == NULL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663 return;
3664
3665 portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
3666 portp->uartaddr = (portp->portnr & 0x07) << 4;
3667 portp->pagenr = panelp->pagenr;
3668 portp->hwid = 0x1;
3669
3670 BRDENABLE(portp->brdnr, portp->pagenr);
3671 stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
3672 BRDDISABLE(portp->brdnr);
3673}
3674
3675/*****************************************************************************/
3676
3677/*
3678 * Set up the sc26198 registers for a port based on the termios port
3679 * settings.
3680 */
3681
Alan Cox606d0992006-12-08 02:38:45 -08003682static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003684 struct stlbrd *brdp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 unsigned long flags;
3686 unsigned int baudrate;
3687 unsigned char mr0, mr1, mr2, clk;
3688 unsigned char imron, imroff, iopr, ipr;
3689
3690 mr0 = 0;
3691 mr1 = 0;
3692 mr2 = 0;
3693 clk = 0;
3694 iopr = 0;
3695 imron = 0;
3696 imroff = 0;
3697
3698 brdp = stl_brds[portp->brdnr];
Jiri Slaby615e4a72006-12-08 02:38:38 -08003699 if (brdp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 return;
3701
3702/*
3703 * Set up the RX char ignore mask with those RX error types we
3704 * can ignore.
3705 */
3706 portp->rxignoremsk = 0;
3707 if (tiosp->c_iflag & IGNPAR)
3708 portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
3709 SR_RXOVERRUN);
3710 if (tiosp->c_iflag & IGNBRK)
3711 portp->rxignoremsk |= SR_RXBREAK;
3712
3713 portp->rxmarkmsk = SR_RXOVERRUN;
3714 if (tiosp->c_iflag & (INPCK | PARMRK))
3715 portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
3716 if (tiosp->c_iflag & BRKINT)
3717 portp->rxmarkmsk |= SR_RXBREAK;
3718
3719/*
3720 * Go through the char size, parity and stop bits and set all the
3721 * option register appropriately.
3722 */
3723 switch (tiosp->c_cflag & CSIZE) {
3724 case CS5:
3725 mr1 |= MR1_CS5;
3726 break;
3727 case CS6:
3728 mr1 |= MR1_CS6;
3729 break;
3730 case CS7:
3731 mr1 |= MR1_CS7;
3732 break;
3733 default:
3734 mr1 |= MR1_CS8;
3735 break;
3736 }
3737
3738 if (tiosp->c_cflag & CSTOPB)
3739 mr2 |= MR2_STOP2;
3740 else
3741 mr2 |= MR2_STOP1;
3742
3743 if (tiosp->c_cflag & PARENB) {
3744 if (tiosp->c_cflag & PARODD)
3745 mr1 |= (MR1_PARENB | MR1_PARODD);
3746 else
3747 mr1 |= (MR1_PARENB | MR1_PAREVEN);
Jiri Slabyc62429d2006-12-08 02:39:14 -08003748 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 mr1 |= MR1_PARNONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750
3751 mr1 |= MR1_ERRBLOCK;
3752
3753/*
3754 * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
3755 * space for hardware flow control and the like. This should be set to
3756 * VMIN.
3757 */
3758 mr2 |= MR2_RXFIFOHALF;
3759
3760/*
3761 * Calculate the baud rate timers. For now we will just assume that
3762 * the input and output baud are the same. The sc26198 has a fixed
3763 * baud rate table, so only discrete baud rates possible.
3764 */
3765 baudrate = tiosp->c_cflag & CBAUD;
3766 if (baudrate & CBAUDEX) {
3767 baudrate &= ~CBAUDEX;
3768 if ((baudrate < 1) || (baudrate > 4))
3769 tiosp->c_cflag &= ~CBAUDEX;
3770 else
3771 baudrate += 15;
3772 }
3773 baudrate = stl_baudrates[baudrate];
3774 if ((tiosp->c_cflag & CBAUD) == B38400) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003775 if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 baudrate = 57600;
Alan Coxf8ae4762008-07-16 21:56:37 +01003777 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 baudrate = 115200;
Alan Coxf8ae4762008-07-16 21:56:37 +01003779 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780 baudrate = 230400;
Alan Coxf8ae4762008-07-16 21:56:37 +01003781 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 baudrate = 460800;
Alan Coxf8ae4762008-07-16 21:56:37 +01003783 else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 baudrate = (portp->baud_base / portp->custom_divisor);
3785 }
3786 if (baudrate > STL_SC26198MAXBAUD)
3787 baudrate = STL_SC26198MAXBAUD;
3788
Jiri Slabyc62429d2006-12-08 02:39:14 -08003789 if (baudrate > 0)
3790 for (clk = 0; clk < SC26198_NRBAUDS; clk++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 if (baudrate <= sc26198_baudtable[clk])
3792 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793
3794/*
3795 * Check what form of modem signaling is required and set it up.
3796 */
3797 if (tiosp->c_cflag & CLOCAL) {
Alan Coxf8ae4762008-07-16 21:56:37 +01003798 portp->port.flags &= ~ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 } else {
3800 iopr |= IOPR_DCDCOS;
3801 imron |= IR_IOPORT;
Alan Coxf8ae4762008-07-16 21:56:37 +01003802 portp->port.flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 }
3804
3805/*
3806 * Setup sc26198 enhanced modes if we can. In particular we want to
3807 * handle as much of the flow control as possible automatically. As
3808 * well as saving a few CPU cycles it will also greatly improve flow
3809 * control reliability.
3810 */
3811 if (tiosp->c_iflag & IXON) {
3812 mr0 |= MR0_SWFTX | MR0_SWFT;
3813 imron |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003814 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 imroff |= IR_XONXOFF;
Jiri Slabyc62429d2006-12-08 02:39:14 -08003816
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 if (tiosp->c_iflag & IXOFF)
3818 mr0 |= MR0_SWFRX;
3819
3820 if (tiosp->c_cflag & CRTSCTS) {
3821 mr2 |= MR2_AUTOCTS;
3822 mr1 |= MR1_AUTORTS;
3823 }
3824
3825/*
3826 * All sc26198 register values calculated so go through and set
3827 * them all up.
3828 */
3829
Jiri Slabya0564e12006-12-08 02:38:37 -08003830 pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 portp->portnr, portp->panelnr, portp->brdnr);
Jiri Slabya0564e12006-12-08 02:38:37 -08003832 pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
3833 pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
3834 pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
3836 tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Alan Coxb65b5b52006-06-27 02:54:05 -07003838 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 BRDENABLE(portp->brdnr, portp->pagenr);
3840 stl_sc26198setreg(portp, IMR, 0);
3841 stl_sc26198updatereg(portp, MR0, mr0);
3842 stl_sc26198updatereg(portp, MR1, mr1);
3843 stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
3844 stl_sc26198updatereg(portp, MR2, mr2);
3845 stl_sc26198updatereg(portp, IOPIOR,
3846 ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
3847
3848 if (baudrate > 0) {
3849 stl_sc26198setreg(portp, TXCSR, clk);
3850 stl_sc26198setreg(portp, RXCSR, clk);
3851 }
3852
3853 stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
3854 stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
3855
3856 ipr = stl_sc26198getreg(portp, IPR);
3857 if (ipr & IPR_DCD)
3858 portp->sigs &= ~TIOCM_CD;
3859 else
3860 portp->sigs |= TIOCM_CD;
3861
3862 portp->imr = (portp->imr & ~imroff) | imron;
3863 stl_sc26198setreg(portp, IMR, portp->imr);
3864 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003865 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866}
3867
3868/*****************************************************************************/
3869
3870/*
3871 * Set the state of the DTR and RTS signals.
3872 */
3873
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003874static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875{
3876 unsigned char iopioron, iopioroff;
3877 unsigned long flags;
3878
Jiri Slabya0564e12006-12-08 02:38:37 -08003879 pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
3880 dtr, rts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881
3882 iopioron = 0;
3883 iopioroff = 0;
3884 if (dtr == 0)
3885 iopioroff |= IPR_DTR;
3886 else if (dtr > 0)
3887 iopioron |= IPR_DTR;
3888 if (rts == 0)
3889 iopioroff |= IPR_RTS;
3890 else if (rts > 0)
3891 iopioron |= IPR_RTS;
3892
Alan Coxb65b5b52006-06-27 02:54:05 -07003893 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 BRDENABLE(portp->brdnr, portp->pagenr);
3895 stl_sc26198setreg(portp, IOPIOR,
3896 ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
3897 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003898 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899}
3900
3901/*****************************************************************************/
3902
3903/*
3904 * Return the state of the signals.
3905 */
3906
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003907static int stl_sc26198getsignals(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908{
3909 unsigned char ipr;
3910 unsigned long flags;
3911 int sigs;
3912
Jiri Slabya0564e12006-12-08 02:38:37 -08003913 pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Alan Coxb65b5b52006-06-27 02:54:05 -07003915 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 BRDENABLE(portp->brdnr, portp->pagenr);
3917 ipr = stl_sc26198getreg(portp, IPR);
3918 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07003919 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920
3921 sigs = 0;
3922 sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
3923 sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
3924 sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
3925 sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
3926 sigs |= TIOCM_DSR;
Jesper Juhl014c2542006-01-15 02:37:08 +01003927 return sigs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928}
3929
3930/*****************************************************************************/
3931
3932/*
3933 * Enable/Disable the Transmitter and/or Receiver.
3934 */
3935
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003936static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937{
3938 unsigned char ccr;
3939 unsigned long flags;
3940
Jiri Slabya0564e12006-12-08 02:38:37 -08003941 pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942
3943 ccr = portp->crenable;
3944 if (tx == 0)
3945 ccr &= ~CR_TXENABLE;
3946 else if (tx > 0)
3947 ccr |= CR_TXENABLE;
3948 if (rx == 0)
3949 ccr &= ~CR_RXENABLE;
3950 else if (rx > 0)
3951 ccr |= CR_RXENABLE;
3952
Alan Coxb65b5b52006-06-27 02:54:05 -07003953 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954 BRDENABLE(portp->brdnr, portp->pagenr);
3955 stl_sc26198setreg(portp, SCCR, ccr);
3956 BRDDISABLE(portp->brdnr);
3957 portp->crenable = ccr;
Alan Coxb65b5b52006-06-27 02:54:05 -07003958 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959}
3960
3961/*****************************************************************************/
3962
3963/*
3964 * Start/stop the Transmitter and/or Receiver.
3965 */
3966
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08003967static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968{
3969 unsigned char imr;
3970 unsigned long flags;
3971
Jiri Slabya0564e12006-12-08 02:38:37 -08003972 pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
3974 imr = portp->imr;
3975 if (tx == 0)
3976 imr &= ~IR_TXRDY;
3977 else if (tx == 1)
3978 imr |= IR_TXRDY;
3979 if (rx == 0)
3980 imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
3981 else if (rx > 0)
3982 imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
3983
Alan Coxb65b5b52006-06-27 02:54:05 -07003984 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985 BRDENABLE(portp->brdnr, portp->pagenr);
3986 stl_sc26198setreg(portp, IMR, imr);
3987 BRDDISABLE(portp->brdnr);
3988 portp->imr = imr;
3989 if (tx > 0)
3990 set_bit(ASYI_TXBUSY, &portp->istate);
Alan Coxb65b5b52006-06-27 02:54:05 -07003991 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992}
3993
3994/*****************************************************************************/
3995
3996/*
3997 * Disable all interrupts from this port.
3998 */
3999
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004000static void stl_sc26198disableintrs(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001{
4002 unsigned long flags;
4003
Jiri Slabya0564e12006-12-08 02:38:37 -08004004 pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
Alan Coxb65b5b52006-06-27 02:54:05 -07004006 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 BRDENABLE(portp->brdnr, portp->pagenr);
4008 portp->imr = 0;
4009 stl_sc26198setreg(portp, IMR, 0);
4010 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004011 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012}
4013
4014/*****************************************************************************/
4015
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004016static void stl_sc26198sendbreak(struct stlport *portp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017{
4018 unsigned long flags;
4019
Jiri Slabya0564e12006-12-08 02:38:37 -08004020 pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021
Alan Coxb65b5b52006-06-27 02:54:05 -07004022 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 BRDENABLE(portp->brdnr, portp->pagenr);
4024 if (len == 1) {
4025 stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
4026 portp->stats.txbreaks++;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004027 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
Jiri Slabyc62429d2006-12-08 02:39:14 -08004029
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004031 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032}
4033
4034/*****************************************************************************/
4035
4036/*
4037 * Take flow control actions...
4038 */
4039
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004040static void stl_sc26198flowctrl(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041{
4042 struct tty_struct *tty;
4043 unsigned long flags;
4044 unsigned char mr0;
4045
Jiri Slabya0564e12006-12-08 02:38:37 -08004046 pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
Jiri Slaby615e4a72006-12-08 02:38:38 -08004048 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004050 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004051 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 return;
4053
Alan Coxb65b5b52006-06-27 02:54:05 -07004054 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 BRDENABLE(portp->brdnr, portp->pagenr);
4056
4057 if (state) {
4058 if (tty->termios->c_iflag & IXOFF) {
4059 mr0 = stl_sc26198getreg(portp, MR0);
4060 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4061 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4062 mr0 |= MR0_SWFRX;
4063 portp->stats.rxxon++;
4064 stl_sc26198wait(portp);
4065 stl_sc26198setreg(portp, MR0, mr0);
4066 }
4067/*
4068 * Question: should we return RTS to what it was before? It may
4069 * have been set by an ioctl... Suppose not, since if you have
4070 * hardware flow control set then it is pretty silly to go and
4071 * set the RTS line by hand.
4072 */
4073 if (tty->termios->c_cflag & CRTSCTS) {
4074 stl_sc26198setreg(portp, MR1,
4075 (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
4076 stl_sc26198setreg(portp, IOPIOR,
4077 (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
4078 portp->stats.rxrtson++;
4079 }
4080 } else {
4081 if (tty->termios->c_iflag & IXOFF) {
4082 mr0 = stl_sc26198getreg(portp, MR0);
4083 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4084 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4085 mr0 &= ~MR0_SWFRX;
4086 portp->stats.rxxoff++;
4087 stl_sc26198wait(portp);
4088 stl_sc26198setreg(portp, MR0, mr0);
4089 }
4090 if (tty->termios->c_cflag & CRTSCTS) {
4091 stl_sc26198setreg(portp, MR1,
4092 (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
4093 stl_sc26198setreg(portp, IOPIOR,
4094 (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
4095 portp->stats.rxrtsoff++;
4096 }
4097 }
4098
4099 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004100 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004101 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102}
4103
4104/*****************************************************************************/
4105
4106/*
4107 * Send a flow control character.
4108 */
4109
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004110static void stl_sc26198sendflow(struct stlport *portp, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111{
4112 struct tty_struct *tty;
4113 unsigned long flags;
4114 unsigned char mr0;
4115
Jiri Slabya0564e12006-12-08 02:38:37 -08004116 pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Jiri Slaby615e4a72006-12-08 02:38:38 -08004118 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 return;
Alan Coxd18a7502008-10-13 10:40:07 +01004120 tty = tty_port_tty_get(&portp->port);
Jiri Slaby615e4a72006-12-08 02:38:38 -08004121 if (tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 return;
4123
Alan Coxb65b5b52006-06-27 02:54:05 -07004124 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 BRDENABLE(portp->brdnr, portp->pagenr);
4126 if (state) {
4127 mr0 = stl_sc26198getreg(portp, MR0);
4128 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4129 stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
4130 mr0 |= MR0_SWFRX;
4131 portp->stats.rxxon++;
4132 stl_sc26198wait(portp);
4133 stl_sc26198setreg(portp, MR0, mr0);
4134 } else {
4135 mr0 = stl_sc26198getreg(portp, MR0);
4136 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4137 stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
4138 mr0 &= ~MR0_SWFRX;
4139 portp->stats.rxxoff++;
4140 stl_sc26198wait(portp);
4141 stl_sc26198setreg(portp, MR0, mr0);
4142 }
4143 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004144 spin_unlock_irqrestore(&brd_lock, flags);
Alan Coxd18a7502008-10-13 10:40:07 +01004145 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146}
4147
4148/*****************************************************************************/
4149
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004150static void stl_sc26198flush(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151{
4152 unsigned long flags;
4153
Jiri Slabya0564e12006-12-08 02:38:37 -08004154 pr_debug("stl_sc26198flush(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Jiri Slaby615e4a72006-12-08 02:38:38 -08004156 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 return;
4158
Alan Coxb65b5b52006-06-27 02:54:05 -07004159 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 BRDENABLE(portp->brdnr, portp->pagenr);
4161 stl_sc26198setreg(portp, SCCR, CR_TXRESET);
4162 stl_sc26198setreg(portp, SCCR, portp->crenable);
4163 BRDDISABLE(portp->brdnr);
4164 portp->tx.tail = portp->tx.head;
Alan Coxb65b5b52006-06-27 02:54:05 -07004165 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166}
4167
4168/*****************************************************************************/
4169
4170/*
4171 * Return the current state of data flow on this port. This is only
4172 * really interresting when determining if data has fully completed
4173 * transmission or not... The sc26198 interrupt scheme cannot
4174 * determine when all data has actually drained, so we need to
4175 * check the port statusy register to be sure.
4176 */
4177
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004178static int stl_sc26198datastate(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179{
4180 unsigned long flags;
4181 unsigned char sr;
4182
Jiri Slabya0564e12006-12-08 02:38:37 -08004183 pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Jiri Slaby615e4a72006-12-08 02:38:38 -08004185 if (portp == NULL)
Jesper Juhl014c2542006-01-15 02:37:08 +01004186 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187 if (test_bit(ASYI_TXBUSY, &portp->istate))
Jesper Juhl014c2542006-01-15 02:37:08 +01004188 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
Alan Coxb65b5b52006-06-27 02:54:05 -07004190 spin_lock_irqsave(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 BRDENABLE(portp->brdnr, portp->pagenr);
4192 sr = stl_sc26198getreg(portp, SR);
4193 BRDDISABLE(portp->brdnr);
Alan Coxb65b5b52006-06-27 02:54:05 -07004194 spin_unlock_irqrestore(&brd_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
Jesper Juhl014c2542006-01-15 02:37:08 +01004196 return (sr & SR_TXEMPTY) ? 0 : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197}
4198
4199/*****************************************************************************/
4200
4201/*
4202 * Delay for a small amount of time, to give the sc26198 a chance
4203 * to process a command...
4204 */
4205
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004206static void stl_sc26198wait(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207{
4208 int i;
4209
Jiri Slabya0564e12006-12-08 02:38:37 -08004210 pr_debug("stl_sc26198wait(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211
Jiri Slaby615e4a72006-12-08 02:38:38 -08004212 if (portp == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 return;
4214
Jiri Slabyc62429d2006-12-08 02:39:14 -08004215 for (i = 0; i < 20; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216 stl_sc26198getglobreg(portp, TSTR);
4217}
4218
4219/*****************************************************************************/
4220
4221/*
4222 * If we are TX flow controlled and in IXANY mode then we may
4223 * need to unflow control here. We gotta do this because of the
4224 * automatic flow control modes of the sc26198.
4225 */
4226
Jiri Slaby60be4812006-12-08 02:38:40 -08004227static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228{
4229 unsigned char mr0;
4230
4231 mr0 = stl_sc26198getreg(portp, MR0);
4232 stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
4233 stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
4234 stl_sc26198wait(portp);
4235 stl_sc26198setreg(portp, MR0, mr0);
4236 clear_bit(ASYI_TXFLOWED, &portp->istate);
4237}
4238
4239/*****************************************************************************/
4240
4241/*
4242 * Interrupt service routine for sc26198 panels.
4243 */
4244
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004245static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246{
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004247 struct stlport *portp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 unsigned int iack;
4249
Alan Coxb65b5b52006-06-27 02:54:05 -07004250 spin_lock(&brd_lock);
4251
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252/*
4253 * Work around bug in sc26198 chip... Cannot have A6 address
4254 * line of UART high, else iack will be returned as 0.
4255 */
4256 outb(0, (iobase + 1));
4257
4258 iack = inb(iobase + XP_IACK);
4259 portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
4260
4261 if (iack & IVR_RXDATA)
4262 stl_sc26198rxisr(portp, iack);
4263 else if (iack & IVR_TXDATA)
4264 stl_sc26198txisr(portp);
4265 else
4266 stl_sc26198otherisr(portp, iack);
Alan Coxb65b5b52006-06-27 02:54:05 -07004267
4268 spin_unlock(&brd_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271/*****************************************************************************/
4272
4273/*
4274 * Transmit interrupt handler. This has gotta be fast! Handling TX
4275 * chars is pretty simple, stuff as many as possible from the TX buffer
4276 * into the sc26198 FIFO.
4277 * In practice it is possible that interrupts are enabled but that the
4278 * port has been hung up. Need to handle not having any TX buffer here,
4279 * this is done by using the side effect that head and tail will also
4280 * be NULL if the buffer has been freed.
4281 */
4282
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004283static void stl_sc26198txisr(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284{
Alan Coxd18a7502008-10-13 10:40:07 +01004285 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 unsigned int ioaddr;
4287 unsigned char mr0;
4288 int len, stlen;
4289 char *head, *tail;
4290
Jiri Slabya0564e12006-12-08 02:38:37 -08004291 pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
4293 ioaddr = portp->ioaddr;
4294 head = portp->tx.head;
4295 tail = portp->tx.tail;
4296 len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
4297 if ((len == 0) || ((len < STL_TXBUFLOW) &&
4298 (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
4299 set_bit(ASYI_TXLOW, &portp->istate);
Alan Coxd18a7502008-10-13 10:40:07 +01004300 tty = tty_port_tty_get(&portp->port);
4301 if (tty) {
4302 tty_wakeup(tty);
4303 tty_kref_put(tty);
4304 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 }
4306
4307 if (len == 0) {
4308 outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
4309 mr0 = inb(ioaddr + XP_DATA);
4310 if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
4311 portp->imr &= ~IR_TXRDY;
4312 outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
4313 outb(portp->imr, (ioaddr + XP_DATA));
4314 clear_bit(ASYI_TXBUSY, &portp->istate);
4315 } else {
4316 mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
4317 outb(mr0, (ioaddr + XP_DATA));
4318 }
4319 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004320 len = min(len, SC26198_TXFIFOSIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 portp->stats.txtotal += len;
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004322 stlen = min_t(unsigned int, len,
4323 (portp->tx.buf + STL_TXBUFSIZE) - tail);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 outb(GTXFIFO, (ioaddr + XP_ADDR));
4325 outsb((ioaddr + XP_DATA), tail, stlen);
4326 len -= stlen;
4327 tail += stlen;
4328 if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
4329 tail = portp->tx.buf;
4330 if (len > 0) {
4331 outsb((ioaddr + XP_DATA), tail, len);
4332 tail += len;
4333 }
4334 portp->tx.tail = tail;
4335 }
4336}
4337
4338/*****************************************************************************/
4339
4340/*
4341 * Receive character interrupt handler. Determine if we have good chars
4342 * or bad chars and then process appropriately. Good chars are easy
4343 * just shove the lot into the RX buffer and set all status byte to 0.
4344 * If a bad RX char then process as required. This routine needs to be
4345 * fast! In practice it is possible that we get an interrupt on a port
4346 * that is closed. This can happen on hangups - since they completely
4347 * shutdown a port not in user context. Need to handle this case.
4348 */
4349
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004350static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004351{
4352 struct tty_struct *tty;
4353 unsigned int len, buflen, ioaddr;
4354
Jiri Slabya0564e12006-12-08 02:38:37 -08004355 pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356
Alan Coxd18a7502008-10-13 10:40:07 +01004357 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358 ioaddr = portp->ioaddr;
4359 outb(GIBCR, (ioaddr + XP_ADDR));
4360 len = inb(ioaddr + XP_DATA) + 1;
4361
4362 if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
Alan Cox33f0f882006-01-09 20:54:13 -08004363 if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
Jiri Slaby319fe7c2008-02-07 00:16:36 -08004364 len = min_t(unsigned int, len, sizeof(stl_unwanted));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 outb(GRXFIFO, (ioaddr + XP_ADDR));
4366 insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
4367 portp->stats.rxlost += len;
4368 portp->stats.rxtotal += len;
4369 } else {
Jiri Slaby843b5682006-12-08 02:39:12 -08004370 len = min(len, buflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371 if (len > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -08004372 unsigned char *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373 outb(GRXFIFO, (ioaddr + XP_ADDR));
Alan Cox33f0f882006-01-09 20:54:13 -08004374 tty_prepare_flip_string(tty, &ptr, len);
4375 insb((ioaddr + XP_DATA), ptr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376 tty_schedule_flip(tty);
4377 portp->stats.rxtotal += len;
4378 }
4379 }
4380 } else {
4381 stl_sc26198rxbadchars(portp);
4382 }
4383
4384/*
4385 * If we are TX flow controlled and in IXANY mode then we may need
4386 * to unflow control here. We gotta do this because of the automatic
4387 * flow control modes of the sc26198.
4388 */
4389 if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
Jiri Slaby615e4a72006-12-08 02:38:38 -08004390 if ((tty != NULL) &&
4391 (tty->termios != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392 (tty->termios->c_iflag & IXANY)) {
4393 stl_sc26198txunflow(portp, tty);
4394 }
4395 }
Alan Coxd18a7502008-10-13 10:40:07 +01004396 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397}
4398
4399/*****************************************************************************/
4400
4401/*
4402 * Process an RX bad character.
4403 */
4404
Jiri Slaby60be4812006-12-08 02:38:40 -08004405static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406{
4407 struct tty_struct *tty;
4408 unsigned int ioaddr;
4409
Alan Coxd18a7502008-10-13 10:40:07 +01004410 tty = tty_port_tty_get(&portp->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411 ioaddr = portp->ioaddr;
4412
4413 if (status & SR_RXPARITY)
4414 portp->stats.rxparity++;
4415 if (status & SR_RXFRAMING)
4416 portp->stats.rxframing++;
4417 if (status & SR_RXOVERRUN)
4418 portp->stats.rxoverrun++;
4419 if (status & SR_RXBREAK)
4420 portp->stats.rxbreaks++;
4421
Jiri Slaby615e4a72006-12-08 02:38:38 -08004422 if ((tty != NULL) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 ((portp->rxignoremsk & status) == 0)) {
4424 if (portp->rxmarkmsk & status) {
4425 if (status & SR_RXBREAK) {
4426 status = TTY_BREAK;
Alan Coxf8ae4762008-07-16 21:56:37 +01004427 if (portp->port.flags & ASYNC_SAK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428 do_SAK(tty);
4429 BRDENABLE(portp->brdnr, portp->pagenr);
4430 }
Jiri Slabyc62429d2006-12-08 02:39:14 -08004431 } else if (status & SR_RXPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 status = TTY_PARITY;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004433 else if (status & SR_RXFRAMING)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 status = TTY_FRAME;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004435 else if(status & SR_RXOVERRUN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 status = TTY_OVERRUN;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004437 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 status = 0;
Jiri Slabyc62429d2006-12-08 02:39:14 -08004439 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440 status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Alan Cox33f0f882006-01-09 20:54:13 -08004442 tty_insert_flip_char(tty, ch, status);
4443 tty_schedule_flip(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
4445 if (status == 0)
4446 portp->stats.rxtotal++;
4447 }
Alan Coxd18a7502008-10-13 10:40:07 +01004448 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449}
4450
4451/*****************************************************************************/
4452
4453/*
4454 * Process all characters in the RX FIFO of the UART. Check all char
4455 * status bytes as well, and process as required. We need to check
4456 * all bytes in the FIFO, in case some more enter the FIFO while we
4457 * are here. To get the exact character error type we need to switch
4458 * into CHAR error mode (that is why we need to make sure we empty
4459 * the FIFO).
4460 */
4461
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004462static void stl_sc26198rxbadchars(struct stlport *portp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463{
4464 unsigned char status, mr1;
4465 char ch;
4466
4467/*
4468 * To get the precise error type for each character we must switch
4469 * back into CHAR error mode.
4470 */
4471 mr1 = stl_sc26198getreg(portp, MR1);
4472 stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
4473
4474 while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
4475 stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
4476 ch = stl_sc26198getreg(portp, RXFIFO);
4477 stl_sc26198rxbadch(portp, status, ch);
4478 }
4479
4480/*
4481 * To get correct interrupt class we must switch back into BLOCK
4482 * error mode.
4483 */
4484 stl_sc26198setreg(portp, MR1, mr1);
4485}
4486
4487/*****************************************************************************/
4488
4489/*
4490 * Other interrupt handler. This includes modem signals, flow
4491 * control actions, etc. Most stuff is left to off-level interrupt
4492 * processing time.
4493 */
4494
Jiri Slabyca7ed0f2006-12-08 02:38:39 -08004495static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496{
4497 unsigned char cir, ipr, xisr;
4498
Jiri Slabya0564e12006-12-08 02:38:37 -08004499 pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500
4501 cir = stl_sc26198getglobreg(portp, CIR);
4502
4503 switch (cir & CIR_SUBTYPEMASK) {
4504 case CIR_SUBCOS:
4505 ipr = stl_sc26198getreg(portp, IPR);
4506 if (ipr & IPR_DCDCHANGE) {
Jiri Slabyccfea3c2008-02-07 00:16:39 -08004507 stl_cd_change(portp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508 portp->stats.modem++;
4509 }
4510 break;
4511 case CIR_SUBXONXOFF:
4512 xisr = stl_sc26198getreg(portp, XISR);
4513 if (xisr & XISR_RXXONGOT) {
4514 set_bit(ASYI_TXFLOWED, &portp->istate);
4515 portp->stats.txxoff++;
4516 }
4517 if (xisr & XISR_RXXOFFGOT) {
4518 clear_bit(ASYI_TXFLOWED, &portp->istate);
4519 portp->stats.txxon++;
4520 }
4521 break;
4522 case CIR_SUBBREAK:
4523 stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
4524 stl_sc26198rxbadchars(portp);
4525 break;
4526 default:
4527 break;
4528 }
4529}
4530
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004531static void stl_free_isabrds(void)
4532{
4533 struct stlbrd *brdp;
4534 unsigned int i;
4535
4536 for (i = 0; i < stl_nrbrds; i++) {
4537 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4538 continue;
4539
4540 free_irq(brdp->irq, brdp);
4541
4542 stl_cleanup_panels(brdp);
4543
4544 release_region(brdp->ioaddr1, brdp->iosize1);
4545 if (brdp->iosize2 > 0)
4546 release_region(brdp->ioaddr2, brdp->iosize2);
4547
4548 kfree(brdp);
4549 stl_brds[i] = NULL;
4550 }
4551}
4552
Jiri Slaby23b85a12006-12-08 02:38:40 -08004553/*
4554 * Loadable module initialization stuff.
4555 */
4556static int __init stallion_module_init(void)
4557{
Jiri Slaby843b5682006-12-08 02:39:12 -08004558 struct stlbrd *brdp;
4559 struct stlconf conf;
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004560 unsigned int i, j;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004561 int retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004562
4563 printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
4564
4565 spin_lock_init(&stallion_lock);
4566 spin_lock_init(&brd_lock);
4567
Jiri Slabye4151092007-06-08 13:46:52 -07004568 stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
4569 if (!stl_serial) {
4570 retval = -ENOMEM;
4571 goto err;
4572 }
4573
4574 stl_serial->owner = THIS_MODULE;
4575 stl_serial->driver_name = stl_drvname;
4576 stl_serial->name = "ttyE";
4577 stl_serial->major = STL_SERIALMAJOR;
4578 stl_serial->minor_start = 0;
4579 stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
4580 stl_serial->subtype = SERIAL_TYPE_NORMAL;
4581 stl_serial->init_termios = stl_deftermios;
4582 stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
4583 tty_set_operations(stl_serial, &stl_ops);
4584
4585 retval = tty_register_driver(stl_serial);
4586 if (retval) {
4587 printk("STALLION: failed to register serial driver\n");
4588 goto err_frtty;
4589 }
4590
Jiri Slaby843b5682006-12-08 02:39:12 -08004591/*
4592 * Find any dynamically supported boards. That is via module load
4593 * line options.
4594 */
4595 for (i = stl_nrbrds; i < stl_nargs; i++) {
4596 memset(&conf, 0, sizeof(conf));
4597 if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
4598 continue;
4599 if ((brdp = stl_allocbrd()) == NULL)
4600 continue;
4601 brdp->brdnr = i;
4602 brdp->brdtype = conf.brdtype;
4603 brdp->ioaddr1 = conf.ioaddr1;
4604 brdp->ioaddr2 = conf.ioaddr2;
4605 brdp->irq = conf.irq;
4606 brdp->irqtype = conf.irqtype;
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004607 stl_brds[brdp->brdnr] = brdp;
4608 if (stl_brdinit(brdp)) {
4609 stl_brds[brdp->brdnr] = NULL;
Jiri Slaby843b5682006-12-08 02:39:12 -08004610 kfree(brdp);
Ingo Korbb08b5ad2007-06-23 17:16:35 -07004611 } else {
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004612 for (j = 0; j < brdp->nrports; j++)
4613 tty_register_device(stl_serial,
4614 brdp->brdnr * STL_MAXPORTS + j, NULL);
Jiri Slaby843b5682006-12-08 02:39:12 -08004615 stl_nrbrds = i + 1;
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004616 }
Jiri Slaby843b5682006-12-08 02:39:12 -08004617 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004618
Jiri Slaby79cfe7a2006-12-08 02:39:14 -08004619 /* this has to be _after_ isa finding because of locking */
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004620 retval = pci_register_driver(&stl_pcidriver);
Jiri Slabye4151092007-06-08 13:46:52 -07004621 if (retval && stl_nrbrds == 0) {
4622 printk(KERN_ERR "STALLION: can't register pci driver\n");
4623 goto err_unrtty;
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004624 }
Jiri Slaby23b85a12006-12-08 02:38:40 -08004625
4626/*
4627 * Set up a character driver for per board stuff. This is mainly used
4628 * to do stats ioctls on the ports.
4629 */
4630 if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
4631 printk("STALLION: failed to register serial board device\n");
4632
4633 stallion_class = class_create(THIS_MODULE, "staliomem");
Jiri Slabye4151092007-06-08 13:46:52 -07004634 if (IS_ERR(stallion_class))
4635 printk("STALLION: failed to create class\n");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004636 for (i = 0; i < 4; i++)
Greg Kroah-Hartman03457cd2008-07-21 20:03:34 -07004637 device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
4638 NULL, "staliomem%d", i);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004639
Jiri Slaby23b85a12006-12-08 02:38:40 -08004640 return 0;
Jiri Slabye4151092007-06-08 13:46:52 -07004641err_unrtty:
4642 tty_unregister_driver(stl_serial);
4643err_frtty:
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004644 put_tty_driver(stl_serial);
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004645err:
4646 return retval;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004647}
4648
4649static void __exit stallion_module_exit(void)
4650{
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004651 struct stlbrd *brdp;
4652 unsigned int i, j;
Jiri Slaby23b85a12006-12-08 02:38:40 -08004653
4654 pr_debug("cleanup_module()\n");
4655
4656 printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
4657 stl_drvversion);
4658
4659/*
4660 * Free up all allocated resources used by the ports. This includes
4661 * memory and interrupts. As part of this process we will also do
4662 * a hangup on every open port - to try to flush out any processes
4663 * hanging onto ports.
4664 */
Jiri Slabyaeaccfe2006-12-08 02:39:16 -08004665 for (i = 0; i < stl_nrbrds; i++) {
4666 if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
4667 continue;
4668 for (j = 0; j < brdp->nrports; j++)
4669 tty_unregister_device(stl_serial,
4670 brdp->brdnr * STL_MAXPORTS + j);
4671 }
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004672
Jiri Slaby23b85a12006-12-08 02:38:40 -08004673 for (i = 0; i < 4; i++)
tonyj@suse.de07c015e2007-08-07 22:28:44 -07004674 device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
Akinobu Mita68fc4fa2007-07-19 01:47:50 -07004675 unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
Jiri Slaby23b85a12006-12-08 02:38:40 -08004676 class_destroy(stallion_class);
4677
Jiri Slabyb1b84fe2006-12-08 02:39:09 -08004678 pci_unregister_driver(&stl_pcidriver);
4679
Jiri Slabyfc06b5c2006-12-08 02:39:13 -08004680 stl_free_isabrds();
Jiri Slabye4151092007-06-08 13:46:52 -07004681
4682 tty_unregister_driver(stl_serial);
4683 put_tty_driver(stl_serial);
Jiri Slaby23b85a12006-12-08 02:38:40 -08004684}
4685
4686module_init(stallion_module_init);
4687module_exit(stallion_module_exit);
4688
4689MODULE_AUTHOR("Greg Ungerer");
4690MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
4691MODULE_LICENSE("GPL");